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> <artifactId>jclouds-vcloud</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </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> <dependency>
<groupId>${project.groupId}</groupId> <groupId>${project.groupId}</groupId>
<artifactId>jclouds-gogrid</artifactId> <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. * 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 * The singatures should match those of ${providerName}AsyncClient, except the returnvals should not be
* wrapped in a ListenableFuture * wrapped in a Future
*/ */
String list(); String list();

View File

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

View File

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

View File

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

View File

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

View File

@ -18,6 +18,16 @@
*/ */
package org.jclouds.aws.ec2.compute.config; 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.imageIds;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy; import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS; 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.aws.ec2.util.EC2Utils.parseHandle;
import static org.jclouds.compute.domain.OsFamily.CENTOS; import static org.jclouds.compute.domain.OsFamily.CENTOS;
import static org.jclouds.compute.domain.OsFamily.UBUNTU; 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.net.URI;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; 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.functions.RunningInstanceToNodeMetadata;
import org.jclouds.aws.ec2.compute.internal.EC2TemplateBuilderImpl; import org.jclouds.aws.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.aws.ec2.compute.options.EC2TemplateOptions; 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.EC2DestroyLoadBalancerStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyNodeStrategy; import org.jclouds.aws.ec2.compute.strategy.EC2DestroyNodeStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2LoadBalanceNodesStrategy; 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.InstanceType;
import org.jclouds.aws.ec2.domain.KeyPair; import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.domain.PlacementGroup; 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.RunningInstance;
import org.jclouds.aws.ec2.domain.Image.ImageType;
import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix; import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix;
import org.jclouds.aws.ec2.options.DescribeImagesOptions; import org.jclouds.aws.ec2.options.DescribeImagesOptions;
import org.jclouds.aws.ec2.predicates.InstancePresent; 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.LoadBalanceNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy; import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl; 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.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; 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.Iterables;
import com.google.common.collect.MapMaker; import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps; 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.AbstractModule;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.Scopes; import com.google.inject.Scopes;
@ -206,13 +216,13 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final EC2Client client; private final EC2AsyncClient client;
private final Map<String, URI> regionMap; private final Map<String, URI> regionMap;
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata; private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
private final ExecutorService executor; private final ExecutorService executor;
@Inject @Inject
protected EC2ListNodesStrategy(EC2Client client, @Region Map<String, URI> regionMap, protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Map<String, URI> regionMap,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.client = client; this.client = client;
@ -222,31 +232,25 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
} }
@Override @Override
public Iterable<? extends ComputeMetadata> list() { public Set<? extends ComputeMetadata> list() {
return listDetailsOnNodesMatching(NodePredicates.all()); return listDetailsOnNodesMatching(NodePredicates.all());
} }
@Override @Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) { public Set<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
final Set<NodeMetadata> nodes = Sets.newHashSet(); 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 @Override
public Void call() throws Exception { public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
Iterables.addAll(nodes, Iterables.transform(Iterables.concat(client.getInstanceServices() return client.getInstanceServices().describeInstancesInRegion(from);
.describeInstancesInRegion(region)), runningInstanceToNodeMetadata));
return null;
} }
}), executor));
}
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, logger, "nodes");
if (exceptions.size() > 0) }, executor, null, logger, "reservations");
throw new RuntimeException(String.format("error parsing nodes in regions: %s", exceptions));
return Iterables.filter(nodes, filter); 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 region = parts[0];
String instanceId = parts[1]; String instanceId = parts[1];
try { try {
RunningInstance runningInstance = Iterables.getOnlyElement(getAllRunningInstancesInRegion(client RunningInstance runningInstance = getOnlyElement(getAllRunningInstancesInRegion(client
.getInstanceServices(), region, instanceId)); .getInstanceServices(), region, instanceId));
return runningInstanceToNodeMetadata.apply(runningInstance); return runningInstanceToNodeMetadata.apply(runningInstance);
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
@ -305,7 +309,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
protected final Map<RegionAndName, KeyPair> credentialsMap(CreateUniqueKeyPair in) { protected final Map<RegionAndName, KeyPair> credentialsMap(CreateUniqueKeyPair in) {
// doesn't seem to clear when someone issues remove(key) // doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in); // return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap(); return newLinkedHashMap();
} }
@Provides @Provides
@ -314,7 +318,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
protected final Map<RegionAndName, String> securityGroupMap(CreateSecurityGroupIfNeeded in) { protected final Map<RegionAndName, String> securityGroupMap(CreateSecurityGroupIfNeeded in) {
// doesn't seem to clear when someone issues remove(key) // doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in); // return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap(); return newLinkedHashMap();
} }
@Provides @Provides
@ -323,7 +327,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
protected final Map<RegionAndName, String> placementGroupMap(CreatePlacementGroupIfNeeded in) { protected final Map<RegionAndName, String> placementGroupMap(CreatePlacementGroupIfNeeded in) {
// doesn't seem to clear when someone issues remove(key) // doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in); // return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap(); return newLinkedHashMap();
} }
@Provides @Provides
@ -340,10 +344,10 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
Set<? extends Size> provideSizes(Set<? extends Location> locations, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) { 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) { for (String ccAmi : ccAmis) {
final String region = ccAmi.split("/")[0]; final String region = ccAmi.split("/")[0];
Location location = Iterables.find(locations, new Predicate<Location>() { Location location = find(locations, new Predicate<Location>() {
@Override @Override
public boolean apply(Location input) { public boolean apply(Location input) {
@ -362,11 +366,11 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
Set<? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap, Set<? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap,
@Provider String providerName) { @Provider String providerName) {
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
Set<Location> locations = Sets.newLinkedHashSet(); Set<Location> locations = newLinkedHashSet();
for (String region : Sets.newLinkedHashSet(availabilityZoneToRegionMap.values())) { for (String region : newLinkedHashSet(availabilityZoneToRegionMap.values())) {
locations.add(new LocationImpl(LocationScope.REGION, region, region, ec2)); 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 @Override
public String apply(Location from) { public String apply(Location from) {
return from.getId(); return from.getId();
@ -391,7 +395,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
String[] amiOwners(@Named(PROPERTY_EC2_AMI_OWNERS) String amiOwners) { String[] amiOwners(@Named(PROPERTY_EC2_AMI_OWNERS) String amiOwners) {
if (amiOwners.trim().equals("")) if (amiOwners.trim().equals(""))
return new String[] {}; return new String[] {};
return Iterables.toArray(Splitter.on(',').split(amiOwners), String.class); return toArray(Splitter.on(',').split(amiOwners), String.class);
} }
@Provides @Provides
@ -400,7 +404,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
String[] ccAmis(@Named(PROPERTY_EC2_CC_AMIs) String ccAmis) { String[] ccAmis(@Named(PROPERTY_EC2_CC_AMIs) String ccAmis) {
if (ccAmis.trim().equals("")) if (ccAmis.trim().equals(""))
return new String[] {}; return new String[] {};
return Iterables.toArray(Splitter.on(',').split(ccAmis), String.class); return toArray(Splitter.on(',').split(ccAmis), String.class);
} }
@Provides @Provides
@ -416,54 +420,62 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected Map<RegionAndName, ? extends Image> provideImages(final EC2Client sync, protected Map<RegionAndName, ? extends Image> provideImages(@Region Map<String, URI> regionMap,
@Region Map<String, URI> regionMap, final LogHolder holder, Function<ComputeMetadata, String> indexer, DescribeImagesParallel describer, LogHolder holder, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis,
@Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis, @Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners, @Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners, final ImageParser parser,
final ImageParser parser, final ConcurrentMap<RegionAndName, Image> images, final ConcurrentMap<RegionAndName, Image> images) throws InterruptedException, ExecutionException,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) throws InterruptedException, TimeoutException {
ExecutionException, TimeoutException {
if (amiOwners.length == 0) { if (amiOwners.length == 0) {
holder.logger.debug(">> no owners specified, skipping image parsing"); holder.logger.debug(">> no owners specified, skipping image parsing");
} else { } else {
holder.logger.debug(">> providing images"); holder.logger.debug(">> providing images");
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap(); Iterable<Entry<String, DescribeImagesOptions>> queries = concat(getDescribeQueriesForOwnersInRegions(
final DescribeImagesOptions options; regionMap, amiOwners).entrySet(), ccAmisToDescribeQueries(ccAmis).entrySet());
if (amiOwners.length == 1 && amiOwners[0].equals("*"))
options = new DescribeImagesOptions(); Iterable<? extends Image> parsedImages = filter(transform(describer.apply(queries), parser), Predicates
else .notNull());
options = ownedBy(amiOwners);
for (final String region : regionMap.keySet()) { images.putAll(Maps.uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
@Override @Override
public Void call() throws Exception { public RegionAndName apply(Image from) {
Set<org.jclouds.aws.ec2.domain.Image> matchingImages = sync.getAMIServices().describeImagesInRegion( return new RegionAndName(from.getLocation().getId(), from.getProviderId());
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());
} }
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()); holder.logger.debug("<< images(%d)", images.size());
} }
return images; 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) { if (imageId != null) {
String[] regionName = imageId.split("/"); String[] regionName = imageId.split("/");
checkArgument(regionName.length == 2, 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]); RegionAndName key = new RegionAndName(regionName[0], regionName[1]);
try { try {
return imageMap.get(key); 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.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Future;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -48,7 +49,6 @@ import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
/** /**
* creates futures that correlate to * creates futures that correlate to
@ -56,8 +56,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class EC2RunNodesAndAddToSetStrategy implements public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
RunNodesAndAddToSetStrategy {
@Resource @Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER) @Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -79,8 +78,7 @@ public class EC2RunNodesAndAddToSetStrategy implements
EC2Client client, EC2Client client,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions, CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
@Named("PRESENT") Predicate<RunningInstance> instancePresent, @Named("PRESENT") Predicate<RunningInstance> instancePresent,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, ComputeUtils utils) {
ComputeUtils utils) {
this.client = client; this.client = client;
this.instancePresent = instancePresent; this.instancePresent = instancePresent;
this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions; this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
@ -89,12 +87,11 @@ public class EC2RunNodesAndAddToSetStrategy implements
} }
@Override @Override
public Map<?, ListenableFuture<Void>> execute(String tag, int count, public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes) { Map<NodeMetadata, Exception> badNodes) {
Reservation reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances( Reservation<? extends RunningInstance> reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(tag,
tag, count, template); count, template);
Iterable<String> ids = transform(reservation, instanceToId); Iterable<String> ids = transform(reservation, instanceToId);
@ -104,28 +101,25 @@ public class EC2RunNodesAndAddToSetStrategy implements
all(reservation, instancePresent); all(reservation, instancePresent);
logger.debug("<< present instances(%s)", idsString); logger.debug("<< present instances(%s)", idsString);
return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap( return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(template.getOptions(), transform(
template.getOptions(), transform(reservation, reservation, runningInstanceToNodeMetadata), goodNodes, badNodes);
runningInstanceToNodeMetadata), goodNodes, badNodes);
} }
@VisibleForTesting @VisibleForTesting
Reservation createKeyPairAndSecurityGroupsAsNeededThenRunInstances( Reservation<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String tag, int count,
String tag, int count, Template template) { Template template) {
String region = getRegionFromLocationOrNull(template.getLocation()); String region = getRegionFromLocationOrNull(template.getLocation());
String zone = getZoneFromLocationOrNull(template.getLocation()); String zone = getZoneFromLocationOrNull(template.getLocation());
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region,
.execute(region, tag, template); tag, template);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug( logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count, region, zone, template
">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", .getImage().getProviderId(), instanceOptions.buildFormParameters());
count, region, zone, template.getImage().getProviderId(),
instanceOptions.buildFormParameters());
return client.getInstanceServices().runInstancesInRegion(region, zone, return client.getInstanceServices().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
template.getImage().getProviderId(), 1, count, instanceOptions); count, instanceOptions);
} }
} }

View File

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

View File

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

View File

@ -57,7 +57,7 @@ public interface AMIClient {
* @see DescribeImagesOptions * @see DescribeImagesOptions
*/ */
@Timeout(duration = 300, timeUnit = TimeUnit.SECONDS) @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. * 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.Map;
import java.util.Set; import java.util.Set;
import com.google.common.util.concurrent.ListenableFuture;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.ws.rs.FormParam; 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.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/** /**
* Provides access to EC2 Instance Services via their REST API. * Provides access to EC2 Instance Services via their REST API.
* <p/> * <p/>
@ -82,7 +81,7 @@ public interface InstanceAsyncClient {
@FormParams(keys = ACTION, values = "DescribeInstances") @FormParams(keys = ACTION, values = "DescribeInstances")
@XMLResponseParser(DescribeInstancesResponseHandler.class) @XMLResponseParser(DescribeInstancesResponseHandler.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<Reservation>> describeInstancesInRegion( ListenableFuture<Set<? extends Reservation<? extends RunningInstance>>> describeInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds); @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
@ -93,8 +92,7 @@ public interface InstanceAsyncClient {
@Path("/") @Path("/")
@FormParams(keys = ACTION, values = "RunInstances") @FormParams(keys = ACTION, values = "RunInstances")
@XMLResponseParser(RunInstancesResponseHandler.class) @XMLResponseParser(RunInstancesResponseHandler.class)
ListenableFuture<Reservation> runInstancesInRegion( ListenableFuture<Reservation<? extends RunningInstance>> runInstancesInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone, @Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone,
@FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount, @FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
@FormParam("MaxCount") int maxCount, RunInstancesOptions... options); @FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
@ -105,8 +103,7 @@ public interface InstanceAsyncClient {
@POST @POST
@Path("/") @Path("/")
@FormParams(keys = ACTION, values = "RebootInstances") @FormParams(keys = ACTION, values = "RebootInstances")
ListenableFuture<Void> rebootInstancesInRegion( ListenableFuture<Void> rebootInstancesInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds); @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
/** /**
@ -116,7 +113,7 @@ public interface InstanceAsyncClient {
@Path("/") @Path("/")
@FormParams(keys = ACTION, values = "TerminateInstances") @FormParams(keys = ACTION, values = "TerminateInstances")
@XMLResponseParser(InstanceStateChangeHandler.class) @XMLResponseParser(InstanceStateChangeHandler.class)
ListenableFuture<? extends Set<InstanceStateChange>> terminateInstancesInRegion( ListenableFuture<Set<? extends InstanceStateChange>> terminateInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds); @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
@ -127,7 +124,7 @@ public interface InstanceAsyncClient {
@Path("/") @Path("/")
@FormParams(keys = ACTION, values = "StopInstances") @FormParams(keys = ACTION, values = "StopInstances")
@XMLResponseParser(InstanceStateChangeHandler.class) @XMLResponseParser(InstanceStateChangeHandler.class)
ListenableFuture<? extends Set<InstanceStateChange>> stopInstancesInRegion( ListenableFuture<Set<? extends InstanceStateChange>> stopInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @FormParam("Force") boolean force, @EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @FormParam("Force") boolean force,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds); @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
@ -138,7 +135,7 @@ public interface InstanceAsyncClient {
@Path("/") @Path("/")
@FormParams(keys = ACTION, values = "StartInstances") @FormParams(keys = ACTION, values = "StartInstances")
@XMLResponseParser(InstanceStateChangeHandler.class) @XMLResponseParser(InstanceStateChangeHandler.class)
ListenableFuture<? extends Set<InstanceStateChange>> startInstancesInRegion( ListenableFuture<Set<? extends InstanceStateChange>> startInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds); @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
@ -182,8 +179,7 @@ public interface InstanceAsyncClient {
@Path("/") @Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "kernel" }) @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "kernel" })
@XMLResponseParser(StringValueHandler.class) @XMLResponseParser(StringValueHandler.class)
ListenableFuture<String> getKernelForInstanceInRegion( ListenableFuture<String> getKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId); @FormParam("InstanceId") String instanceId);
/** /**
@ -247,8 +243,7 @@ public interface InstanceAsyncClient {
@POST @POST
@Path("/") @Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "kernel" }) @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "kernel" })
ListenableFuture<Void> resetKernelForInstanceInRegion( ListenableFuture<Void> resetKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId); @FormParam("InstanceId") String instanceId);
/** /**
@ -257,8 +252,7 @@ public interface InstanceAsyncClient {
@POST @POST
@Path("/") @Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "userData" }) @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "userData" })
ListenableFuture<Void> setUserDataForInstanceInRegion( ListenableFuture<Void> setUserDataForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId, @FormParam("InstanceId") String instanceId,
@FormParam("Value") @ParamParser(ConvertUnencodedBytesToBase64EncodedString.class) byte[] unencodedData); @FormParam("Value") @ParamParser(ConvertUnencodedBytesToBase64EncodedString.class) byte[] unencodedData);
@ -268,8 +262,7 @@ public interface InstanceAsyncClient {
@POST @POST
@Path("/") @Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "ramdisk" }) @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "ramdisk" })
ListenableFuture<Void> setRamdiskForInstanceInRegion( ListenableFuture<Void> setRamdiskForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId, @FormParam("Value") String ramdisk); @FormParam("InstanceId") String instanceId, @FormParam("Value") String ramdisk);
/** /**
@ -278,8 +271,7 @@ public interface InstanceAsyncClient {
@POST @POST
@Path("/") @Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "kernel" }) @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "kernel" })
ListenableFuture<Void> setKernelForInstanceInRegion( ListenableFuture<Void> setKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId, @FormParam("Value") String kernel); @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" * @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); String... instanceIds);
/** /**
@ -141,7 +141,7 @@ public interface InstanceClient {
* /> * />
* @see RunInstancesOptions * @see RunInstancesOptions
*/ */
Reservation runInstancesInRegion(@Nullable String region, Reservation<? extends RunningInstance> runInstancesInRegion(@Nullable String region,
@Nullable String nullableAvailabilityZone, String imageId, @Nullable String nullableAvailabilityZone, String imageId,
int minCount, int maxCount, RunInstancesOptions... options); 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" * @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); String... instanceIds);
/** /**
@ -199,7 +199,7 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html" * @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); 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" * @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); String... instanceIds);
/** /**

View File

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

View File

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

View File

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

View File

@ -38,14 +38,14 @@ import org.jclouds.aws.s3.options.PutObjectOptions;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.http.options.GetOptions; 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. * Provides access to S3 via their REST API.
* <p/> * <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 * processing will be wrapped in an {@link ExecutionException} as documented in
* {@link ListenableFuture#get()}. * {@link Future#get()}.
* *
* @author Adrian Cole * @author Adrian Cole
* @author James Murty * @author James Murty
@ -85,7 +85,7 @@ public interface S3Client {
* namespace of the object you are retrieving * namespace of the object you are retrieving
* @param key * @param key
* unique key in the s3Bucket identifying the object * 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. * or {@link S3Object#NOT_FOUND} if not present.
* *
* @throws org.jclouds.http.HttpResponseException * @throws org.jclouds.http.HttpResponseException
@ -231,7 +231,7 @@ public interface S3Client {
* *
* @param bucketName * @param bucketName
* namespace of the objects you wish to list * 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. * S3Objects it contains or {@link BoundedList<ObjectMetadata>#NOT_FOUND} if not present.
* @see ListBucketOptions * @see ListBucketOptions
* *

View File

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

View File

@ -58,7 +58,7 @@ import com.google.common.collect.Multimap;
* <p/> * <p/>
* // this will copy the object, provided it wasn't modified since yesterday. * // 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. * // 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", * "destinationBucket", "destinationName",
* overrideMetadataWith(meta). * overrideMetadataWith(meta).
* ifSourceModifiedSince(new Date().minusDays(1)) * 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.* * import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
* <p/> * <p/>
* S3Client connection = // get connection * 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> * <code>
* *
* @author Adrian Cole * @author Adrian Cole

View File

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

View File

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

View File

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

View File

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

View File

@ -60,20 +60,17 @@ public class EC2RunNodesAndAddToSetStrategyTest {
@Test @Test
public void testZoneAsALocation() { public void testZoneAsALocation() {
assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A, assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A, Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A);
Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A);
} }
@Test @Test
public void testRegionAsALocation() { public void testRegionAsALocation() {
assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1, assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1, null);
Region.AP_SOUTHEAST_1, null);
} }
// // fixtures // // fixtures
public static Iterable<NodeMetadata> containsNodeMetadata( public static Iterable<NodeMetadata> containsNodeMetadata(final NodeMetadata in) {
final NodeMetadata in) {
reportMatcher(new IArgumentMatcher() { reportMatcher(new IArgumentMatcher() {
@Override @Override
@ -92,8 +89,8 @@ public class EC2RunNodesAndAddToSetStrategyTest {
return null; return null;
} }
private void assertRegionAndZoneForLocation(Location location, @SuppressWarnings("unchecked")
String region, String zone) { private void assertRegionAndZoneForLocation(Location location, String region, String zone) {
String imageId = "ami1"; String imageId = "ami1";
String instanceCreatedId = "instance1"; String instanceCreatedId = "instance1";
// setup mocks // setup mocks
@ -102,37 +99,28 @@ public class EC2RunNodesAndAddToSetStrategyTest {
InstanceClient instanceClient = createMock(InstanceClient.class); InstanceClient instanceClient = createMock(InstanceClient.class);
RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class); RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
RunningInstance instance = createMock(RunningInstance.class); RunningInstance instance = createMock(RunningInstance.class);
Reservation reservation = new Reservation(region, ImmutableSet Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region, ImmutableSet
.<String> of(), ImmutableSet.<RunningInstance> of(instance), .<String> of(), ImmutableSet.<RunningInstance> of(instance), "ownerId", "requesterId", "reservationId");
"ownerId", "requesterId", "reservationId");
NodeMetadata nodeMetadata = createMock(NodeMetadata.class); NodeMetadata nodeMetadata = createMock(NodeMetadata.class);
// setup expectations // setup expectations
expect(strategy.client.getInstanceServices()).andReturn(instanceClient) expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
.atLeastOnce();
expect( expect(
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region, input.tag,
.execute(region, input.tag, input.template)).andReturn( input.template)).andReturn(ec2Options);
ec2Options); expect(input.template.getLocation()).andReturn(input.location).atLeastOnce();
expect(input.template.getLocation()).andReturn(input.location)
.atLeastOnce();
expect(input.template.getImage()).andReturn(input.image).atLeastOnce(); expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce(); expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
expect( expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, input.count, ec2Options)).andReturn(
instanceClient.runInstancesInRegion(region, zone, imageId, 1, (Reservation)reservation);
input.count, ec2Options)).andReturn(reservation);
expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce(); expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
expect(strategy.instancePresent.apply(instance)).andReturn(true); expect(strategy.instancePresent.apply(instance)).andReturn(true);
expect(input.template.getOptions()).andReturn(input.options) expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
.atLeastOnce();
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn( expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
nodeMetadata);
expect( expect(
strategy.utils strategy.utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(eq(input.options),
.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap( containsNodeMetadata(nodeMetadata), eq(input.nodes), eq(input.badNodes))).andReturn(null);
eq(input.options), containsNodeMetadata(nodeMetadata),
eq(input.nodes), eq(input.badNodes))).andReturn(null);
// replay mocks // replay mocks
replay(instanceClient); replay(instanceClient);
@ -143,8 +131,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
replayStrategy(strategy); replayStrategy(strategy);
// run // run
strategy.execute(input.tag, input.count, input.template, input.nodes, strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes);
input.badNodes);
// verify mocks // verify mocks
verify(instanceClient); verify(instanceClient);
@ -155,12 +142,10 @@ public class EC2RunNodesAndAddToSetStrategyTest {
verifyStrategy(strategy); verifyStrategy(strategy);
} }
private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl( private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl(LocationScope.REGION, Region.AP_SOUTHEAST_1,
LocationScope.REGION, Region.AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1, new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null));
new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null)); private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl(LocationScope.ZONE,
private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl( AvailabilityZone.AP_SOUTHEAST_1A, AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
LocationScope.ZONE, AvailabilityZone.AP_SOUTHEAST_1A,
AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
// ///////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -213,8 +198,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class); Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class);
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class); RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
ComputeUtils utils = createMock(ComputeUtils.class); ComputeUtils utils = createMock(ComputeUtils.class);
return new EC2RunNodesAndAddToSetStrategy(client, return new EC2RunNodesAndAddToSetStrategy(client, createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
instanceStateRunning, runningInstanceToNodeMetadata, utils); 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.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client; import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.Reservation; import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory; import org.jclouds.rest.RestContextFactory;
@ -64,9 +65,9 @@ public class InstanceClientLiveTest {
@Test @Test
void testDescribeInstances() { void testDescribeInstances() {
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.US_WEST_1, Region.AP_SOUTHEAST_1)) { Region.AP_SOUTHEAST_1)) {
Set<Reservation> allResults = client.describeInstancesInRegion(region); Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
assertNotNull(allResults); assertNotNull(allResults);
assert allResults.size() >= 0 : allResults.size(); assert allResults.size() >= 0 : allResults.size();
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -33,14 +33,14 @@ import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.concurrent.Timeout; import org.jclouds.concurrent.Timeout;
import org.jclouds.http.options.GetOptions; 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. * Provides access to Azure Blob via their REST API.
* <p/> * <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 * 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" /> * @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
* @author Adrian Cole * @author Adrian Cole

View File

@ -19,11 +19,12 @@
package org.jclouds.azure.storage.blob.blobstore; package org.jclouds.azure.storage.blob.blobstore;
import static com.google.common.base.Preconditions.checkNotNull; 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 static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import com.google.common.util.concurrent.ListenableFuture;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
@ -58,7 +59,6 @@ import org.jclouds.http.options.GetOptions;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -76,21 +76,19 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
@Inject @Inject
AzureAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils, AzureAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
Location defaultLocation, Set<? extends Location> locations, Set<? extends Location> locations, AzureBlobAsyncClient async,
ContainerToResourceMetadata container2ResourceMd,
AzureBlobAsyncClient async, ContainerToResourceMetadata container2ResourceMd,
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions, ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
ListBlobsResponseToResourceList azure2BlobStoreResourceList, ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
AzureBlobToBlob azureBlob2Blob, BlobToAzureBlob blob2AzureBlob, BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
BlobPropertiesToBlobMetadata blob2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions) { BlobToHttpGetOptions blob2ObjectGetOptions) {
super(context, blobUtils, service, defaultLocation, locations); super(context, blobUtils, service, defaultLocation, locations);
this.async = checkNotNull(async, "async"); this.async = checkNotNull(async, "async");
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd"); this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions, this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
"blobStore2AzureContainerListOptions"); "blobStore2AzureContainerListOptions");
this.azure2BlobStoreResourceList = checkNotNull(azure2BlobStoreResourceList, this.azure2BlobStoreResourceList = checkNotNull(azure2BlobStoreResourceList, "azure2BlobStoreResourceList");
"azure2BlobStoreResourceList");
this.azureBlob2Blob = checkNotNull(azureBlob2Blob, "azureBlob2Blob"); this.azureBlob2Blob = checkNotNull(azureBlob2Blob, "azureBlob2Blob");
this.blob2AzureBlob = checkNotNull(blob2AzureBlob, "blob2AzureBlob"); this.blob2AzureBlob = checkNotNull(blob2AzureBlob, "blob2AzureBlob");
this.blob2BlobMd = checkNotNull(blob2BlobMd, "blob2BlobMd"); this.blob2BlobMd = checkNotNull(blob2BlobMd, "blob2BlobMd");
@ -102,14 +100,14 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
* {@link org.jclouds.azure.storage.options.ListOptions#includeMetadata} option. * {@link org.jclouds.azure.storage.options.ListOptions#includeMetadata} option.
*/ */
@Override @Override
public ListenableFuture<? extends org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>> list() { public ListenableFuture<org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>> list() {
return compose( return compose(
async.listContainers(includeMetadata()), async.listContainers(includeMetadata()),
new Function<BoundedSet<ContainerProperties>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() { new Function<BoundedSet<ContainerProperties>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply( public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
BoundedSet<ContainerProperties> from) { BoundedSet<ContainerProperties> from) {
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd), from
container2ResourceMd), from.getNextMarker()); .getNextMarker());
} }
}, service); }, service);
} }
@ -145,11 +143,9 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
* container name * container name
*/ */
@Override @Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container, public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) {
ListContainerOptions options) {
ListBlobsOptions azureOptions = blobStore2AzureContainerListOptions.apply(options); ListBlobsOptions azureOptions = blobStore2AzureContainerListOptions.apply(options);
ListenableFuture<ListBlobsResponse> returnVal = async.listBlobs(container, azureOptions ListenableFuture<ListBlobsResponse> returnVal = async.listBlobs(container, azureOptions.includeMetadata());
.includeMetadata());
return compose(returnVal, azure2BlobStoreResourceList, service); return compose(returnVal, azure2BlobStoreResourceList, service);
} }
@ -173,8 +169,7 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
* blob key * blob key
*/ */
@Override @Override
public ListenableFuture<Blob> getBlob(String container, String key, public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
org.jclouds.blobstore.options.GetOptions options) {
GetOptions azureOptions = blob2ObjectGetOptions.apply(options); GetOptions azureOptions = blob2ObjectGetOptions.apply(options);
ListenableFuture<AzureBlob> returnVal = async.getBlob(container, key, azureOptions); ListenableFuture<AzureBlob> returnVal = async.getBlob(container, key, azureOptions);
return compose(returnVal, azureBlob2Blob, service); return compose(returnVal, azureBlob2Blob, service);
@ -229,8 +224,7 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
*/ */
@Override @Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) { public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(async.getBlobProperties(container, key), return compose(async.getBlobProperties(container, key), new Function<BlobProperties, BlobMetadata>() {
new Function<BlobProperties, BlobMetadata>() {
@Override @Override
public BlobMetadata apply(BlobProperties from) { 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.concurrent.Timeout;
import org.jclouds.http.HttpResponseException; 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. * 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 * 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. * table, and then store a reference to the data as a message in a queue.
* <p/> * <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 * during processing will be wrapped in an {@link ExecutionException} as documented in
* {@link ListenableFuture#get()}. * {@link Future#get()}.
* *
* @see AzureQueueAsyncClient * @see AzureQueueAsyncClient
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" /> * @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />

View File

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

View File

@ -19,10 +19,7 @@
package org.jclouds.blobstore.internal; package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull; 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.blobstore.options.ListContainerOptions.Builder.recursive;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; 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.options.ListContainerOptions;
import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.blobstore.util.internal.BlobUtilsImpl; import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
import static org.jclouds.concurrent.ConcurrentUtils.*;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
/** /**
@ -62,8 +60,8 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
@Inject @Inject
protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils, protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
Location defaultLocation, Set<? extends Location> locations) { Set<? extends Location> locations) {
this.context = checkNotNull(context, "context"); this.context = checkNotNull(context, "context");
this.blobUtils = checkNotNull(blobUtils, "blobUtils"); this.blobUtils = checkNotNull(blobUtils, "blobUtils");
this.service = checkNotNull(service, "service"); this.service = checkNotNull(service, "service");
@ -92,7 +90,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* container name * container name
*/ */
@Override @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); return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
} }
@ -115,8 +113,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* container name * container name
*/ */
@Override @Override
public ListenableFuture<Long> countBlobs(final String containerName, public ListenableFuture<Long> countBlobs(final String containerName, final ListContainerOptions options) {
final ListContainerOptions options) {
return makeListenable(service.submit(new Callable<Long>() { return makeListenable(service.submit(new Callable<Long>() {
public Long call() throws Exception { public Long call() throws Exception {
return blobUtils.countBlobs(containerName, options); return blobUtils.countBlobs(containerName, options);
@ -144,8 +141,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* container name * container name
*/ */
@Override @Override
public ListenableFuture<Void> clearContainer(final String containerName, public ListenableFuture<Void> clearContainer(final String containerName, final ListContainerOptions options) {
final ListContainerOptions options) {
return makeListenable(service.submit(new Callable<Void>() { return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception { public Void call() throws Exception {
@ -182,8 +178,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* @param directory * @param directory
* virtual path * virtual path
*/ */
public ListenableFuture<Boolean> directoryExists(final String containerName, public ListenableFuture<Boolean> directoryExists(final String containerName, final String directory) {
final String directory) {
return makeListenable(service.submit(new Callable<Boolean>() { return makeListenable(service.submit(new Callable<Boolean>() {
public Boolean call() throws Exception { 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) { public ListenableFuture<Void> createDirectory(final String containerName, final String directory) {
return chain(directoryExists(containerName, directory), return blobUtils.directoryExists(containerName, directory) ? Futures.immediateFuture((Void) null)
new Function<Boolean, ListenableFuture<Void>>() { : makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
@Override
public ListenableFuture<Void> apply(Boolean from) {
if (!from) {
blobUtils.createDirectory(containerName, directory); blobUtils.createDirectory(containerName, directory);
return null;
} }
return immediateFuture(null); }), service);
}
}, service);
} }
/** /**
@ -228,7 +218,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* blob key * blob key
*/ */
@Override @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); return getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
} }
@ -271,8 +261,8 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
} }
@Override @Override
public ListenableFuture<? extends Set<? extends Location>> listAssignableLocations() { public ListenableFuture<Set<? extends Location>> listAssignableLocations() {
return immediateFuture(locations); return Futures.<Set<? extends Location>> immediateFuture(locations);
} }
protected abstract boolean deleteAndVerifyContainerGone(String container); 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); return (int) blobstore.countBlobs(containerName, options);
} }
protected Set<? extends Blob> getAllBlobs() { protected Iterable<Blob> getAllBlobs() {
Set<? extends Blob> returnVal = getAllBlobs.execute(containerName, options); Iterable<Blob> returnVal = getAllBlobs.execute(containerName, options);
if (options != null) { if (options != null) {
for (Blob from : returnVal) for (Blob from : returnVal)
stripPrefix(from); 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.PutBlobsStrategy;
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders; import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
import com.google.common.collect.Sets;
/** /**
* Map representation of a live connection to a Blob Service. * Map representation of a live connection to a Blob Service.
* *
@ -46,10 +48,8 @@ public class BlobMapImpl extends BaseBlobMap<Blob> implements BlobMap {
@Inject @Inject
public BlobMapImpl(BlobStore blobstore, GetBlobsInListStrategy getAllBlobs, public BlobMapImpl(BlobStore blobstore, GetBlobsInListStrategy getAllBlobs,
ContainsValueInListStrategy containsValueStrategy, PutBlobsStrategy putBlobsStrategy, ContainsValueInListStrategy containsValueStrategy, PutBlobsStrategy putBlobsStrategy,
ListContainerAndRecurseThroughFolders listStrategy, String containerName, ListContainerAndRecurseThroughFolders listStrategy, String containerName, ListContainerOptions options) {
ListContainerOptions options) { super(blobstore, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy, containerName, options);
super(blobstore, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy,
containerName, options);
} }
@Override @Override
@ -89,10 +89,9 @@ public class BlobMapImpl extends BaseBlobMap<Blob> implements BlobMap {
return old; return old;
} }
@SuppressWarnings("unchecked")
@Override @Override
public Collection<Blob> values() { public Collection<Blob> values() {
return (Collection<Blob>) getAllBlobs.execute(containerName, options); return Sets.newLinkedHashSet(getAllBlobs.execute(containerName, options));
} }
@Override @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 * // 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> * <code>
* *
* @author Adrian Cole * @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.* * import static org.jclouds.blobstore.options.ListContainerOptions.Builder.*
* <p/> * <p/>
* BlobStore connection = // get connection * 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> * <code>
* *
* @author Adrian Cole * @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.* * import static org.jclouds.blobstore.options.ListOptions.Builder.*
* <p/> * <p/>
* BlobStore connection = // get connection * BlobStore connection = // get connection
* ListenableFuture<BoundedSortedSet<ResourceMetadata>> list = connection.list(maxResults(1000)); * Future<BoundedSortedSet<ResourceMetadata>> list = connection.list(maxResults(1000));
* <code> * <code>
* *
* @author Adrian Cole * @author Adrian Cole

View File

@ -18,8 +18,6 @@
*/ */
package org.jclouds.blobstore.strategy; package org.jclouds.blobstore.strategy;
import java.util.Set;
import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.internal.GetAllBlobsInListAndRetryOnFailure; import org.jclouds.blobstore.strategy.internal.GetAllBlobsInListAndRetryOnFailure;
@ -34,6 +32,6 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(GetAllBlobsInListAndRetryOnFailure.class) @ImplementedBy(GetAllBlobsInListAndRetryOnFailure.class)
public interface GetBlobsInListStrategy { 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; package org.jclouds.blobstore.strategy;
import java.util.Set;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.options.ListContainerOptions; import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders; import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
@ -32,6 +34,6 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(ListContainerAndRecurseThroughFolders.class) @ImplementedBy(ListContainerAndRecurseThroughFolders.class)
public interface ListBlobsInContainer { 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.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -93,7 +93,7 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
Map<StorageMetadata, Exception> exceptions = Maps.newHashMap(); Map<StorageMetadata, Exception> exceptions = Maps.newHashMap();
Iterable<? extends StorageMetadata> toDelete = getResourcesToDelete(containerName, options); Iterable<? extends StorageMetadata> toDelete = getResourcesToDelete(containerName, options);
for (int i = 0; i < 3; i++) { // TODO parameterize for (int i = 0; i < 3; i++) { // TODO parameterize
Map<StorageMetadata, ListenableFuture<?>> responses = Maps.newHashMap(); Map<StorageMetadata, Future<?>> responses = Maps.newHashMap();
try { try {
for (final StorageMetadata md : toDelete) { for (final StorageMetadata md : toDelete) {
String fullPath = parentIsFolder(options, md) ? options.getDir() + "/" String fullPath = parentIsFolder(options, md) ? options.getDir() + "/"

View File

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

View File

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

View File

@ -18,7 +18,14 @@
*/ */
package org.jclouds.blobstore.strategy.internal; 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.List;
import java.util.Set;
import javax.inject.Singleton; 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.Function;
import com.google.common.base.Predicate; 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; import com.google.inject.Inject;
/** /**
@ -52,22 +56,20 @@ public class ListContainerAndRecurseThroughFolders implements ListBlobsInContain
} }
@Override @Override
public Iterable<? extends BlobMetadata> execute(final String containerName, public Set<? extends BlobMetadata> execute(final String containerName, final ListContainerOptions options) {
final ListContainerOptions options) { final List<Iterable<? extends BlobMetadata>> lists = newArrayList();
final List<Iterable<? extends BlobMetadata>> lists = Lists.newArrayList();
Iterable<? extends StorageMetadata> pwdList = lister.execute(containerName, options); 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 @Override
public boolean apply(StorageMetadata input) { public boolean apply(StorageMetadata input) {
return (input.getType() == StorageType.FOLDER || input.getType() == StorageType.RELATIVE_PATH) return (input.getType() == StorageType.FOLDER || input.getType() == StorageType.RELATIVE_PATH)
&& options.isRecursive(); && options.isRecursive();
} }
})) { })) {
String directory = (options.getDir() != null) ? options.getDir() + "/" + md.getName() : md String directory = (options.getDir() != null) ? options.getDir() + "/" + md.getName() : md.getName();
.getName();
lists.add(execute(containerName, options.clone().inDirectory(directory))); 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 @Override
public boolean apply(StorageMetadata input) { public boolean apply(StorageMetadata input) {
return input.getType() == StorageType.BLOB; return input.getType() == StorageType.BLOB;
@ -78,6 +80,6 @@ public class ListContainerAndRecurseThroughFolders implements ListBlobsInContain
return (BlobMetadata) from; 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.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -92,7 +92,7 @@ public class MarkersDeleteDirectoryStrategy implements DeleteDirectoryStrategy {
for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) { for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) {
names.add(directory + suffix); names.add(directory + suffix);
} }
Map<String, ListenableFuture<?>> responses = Maps.newHashMap(); Map<String, Future<?>> responses = Maps.newHashMap();
for (String name : names) { for (String name : names) {
responses.put(name, ablobstore.removeBlob(containerName, name)); 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 org.jclouds.logging.Logger;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -67,7 +67,7 @@ public class PutBlobsStrategyImpl implements PutBlobsStrategy {
@Override @Override
public void execute(String containerName, Iterable<? extends Blob> blobs) { 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) { for (Blob blob : blobs) {
responses.put(blob, ablobstore.putBlob(containerName, blob)); responses.put(blob, ablobstore.putBlob(containerName, blob));
} }

View File

@ -38,6 +38,7 @@ import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Future;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import javax.ws.rs.core.MediaType; 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.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.StorageType;
import static org.jclouds.concurrent.ConcurrentUtils.*;
import org.jclouds.encryption.EncryptionService; import org.jclouds.encryption.EncryptionService;
import org.jclouds.encryption.internal.JCEEncryptionService; import org.jclouds.encryption.internal.JCEEncryptionService;
import org.jclouds.http.BaseJettyTest; 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.collect.Maps;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import com.google.common.io.InputSupplier; import com.google.common.io.InputSupplier;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -108,10 +108,10 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
String key = "constitution.txt"; String key = "constitution.txt";
uploadConstitution(containerName, key); uploadConstitution(containerName, key);
Map<Integer, ListenableFuture<?>> responses = Maps.newHashMap(); Map<Integer, Future<?>> responses = Maps.newHashMap();
for (int i = 0; i < 10; i++) { 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>() { new Function<Blob, Void>() {
@Override @Override
@ -121,7 +121,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
return null; return null;
} }
})); }, this.exec));
} }
Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE, Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE,
"get constitution"); "get constitution");
@ -349,8 +349,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
@DataProvider(name = "delete") @DataProvider(name = "delete")
public Object[][] createData() { public Object[][] createData() {
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" },
{ "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } }; { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
} }
@Test(groups = { "integration", "live" }, dataProvider = "delete") @Test(groups = { "integration", "live" }, dataProvider = "delete")
@ -376,8 +376,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
}); });
assertEquals(Iterables.size(listing), 0, String.format( assertEquals(Iterables.size(listing), 0, String.format(
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key, "deleting %s, we still have %s blobs left in container %s, using encoding %s", key, Iterables
Iterables.size(listing), containerName, LOCAL_ENCODING)); .size(listing), containerName, LOCAL_ENCODING));
} }
@Test(groups = { "integration", "live" }) @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 class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegrationTest {
public abstract void testPutAll() throws InterruptedException, ExecutionException, public abstract void testPutAll() throws InterruptedException, ExecutionException, TimeoutException;
TimeoutException;
public abstract void testEntrySet() throws IOException, InterruptedException, public abstract void testEntrySet() throws IOException, InterruptedException, ExecutionException, TimeoutException;
ExecutionException, TimeoutException;
public abstract void testValues() throws IOException, InterruptedException, ExecutionException, public abstract void testValues() throws IOException, InterruptedException, ExecutionException, TimeoutException;
TimeoutException;
protected Map<String, byte[]> fiveBytes = Maps.transformValues(fiveStrings, protected Map<String, byte[]> fiveBytes = Maps.transformValues(fiveStrings, new Function<String, byte[]>() {
new Function<String, byte[]>() {
public byte[] apply(String from) { public byte[] apply(String from) {
return from.getBytes(); return from.getBytes();
} }
@ -86,13 +82,13 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
@BeforeClass(groups = { "integration", "live" }) @BeforeClass(groups = { "integration", "live" })
@Parameters( { "basedir" }) @Parameters( { "basedir" })
protected void setUpTempDir(@Optional String basedir) throws InterruptedException, protected void setUpTempDir(@Optional String basedir) throws InterruptedException, ExecutionException,
ExecutionException, FileNotFoundException, IOException, TimeoutException { FileNotFoundException, IOException, TimeoutException {
if (basedir == null) { if (basedir == null) {
basedir = System.getProperty("java.io.tmpdir"); basedir = System.getProperty("java.io.tmpdir");
} }
tmpDirectory = basedir + File.separator + "target" + File.separator + "testFiles" tmpDirectory = basedir + File.separator + "target" + File.separator + "testFiles" + File.separator
+ File.separator + getClass().getSimpleName(); + getClass().getSimpleName();
new File(tmpDirectory).mkdirs(); new File(tmpDirectory).mkdirs();
fiveFiles = Maps.newHashMap(); fiveFiles = Maps.newHashMap();
for (Entry<String, String> entry : fiveStrings.entrySet()) { for (Entry<String, String> entry : fiveStrings.entrySet()) {
@ -123,8 +119,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
} }
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public abstract void testRemove() throws IOException, InterruptedException, ExecutionException, public abstract void testRemove() throws IOException, InterruptedException, ExecutionException, TimeoutException;
TimeoutException;
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public void testKeySet() throws InterruptedException, ExecutionException, TimeoutException { 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) protected void addTenObjectsUnderPrefix(String containerName, String prefix) throws InterruptedException {
throws InterruptedException {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
Blob blob = context.getBlobStore().newBlob(prefix + "/" + i); Blob blob = context.getBlobStore().newBlob(prefix + "/" + i);
blob.setPayload(i + "content"); blob.setPayload(i + "content");
@ -160,14 +154,12 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public void testDirectory() throws InterruptedException, UnsupportedEncodingException { public void testDirectory() throws InterruptedException, UnsupportedEncodingException {
String containerName = getContainerName(); String containerName = getContainerName();
try {
String directory = "apps"; String directory = "apps";
Map<String, V> rootMap = createMap(context, containerName); Map<String, V> rootMap = createMap(context, containerName);
Map<String, V> rootRecursiveMap = createMap(context, containerName, recursive()); Map<String, V> rootRecursiveMap = createMap(context, containerName, recursive());
Map<String, V> inDirectoryMap = createMap(context, containerName, inDirectory(directory)); Map<String, V> inDirectoryMap = createMap(context, containerName, inDirectory(directory));
Map<String, V> inDirectoryRecursiveMap = createMap(context, containerName, inDirectory( Map<String, V> inDirectoryRecursiveMap = createMap(context, containerName, inDirectory(directory).recursive());
directory).recursive()); try {
context.getBlobStore().createDirectory(containerName, directory); context.getBlobStore().createDirectory(containerName, directory);
addTenObjectsUnderRoot(containerName); addTenObjectsUnderRoot(containerName);
@ -206,24 +198,22 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
} }
protected void assertConsistencyAwareKeySetEquals(final Map<String, V> map, protected void assertConsistencyAwareKeySetEquals(final Map<String, V> map, final Set<String> expected)
final Set<String> expected) throws InterruptedException { throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
Set<String> toMatch = map.keySet(); Set<String> toMatch = map.keySet();
Set<String> shouldBeEmpty = Sets.difference(expected, toMatch); Set<String> shouldBeEmpty = Sets.difference(expected, toMatch);
assert shouldBeEmpty.size() == 0 : "toMatch has less keys than expected. missing: " assert shouldBeEmpty.size() == 0 : "toMatch has less keys than expected. missing: " + shouldBeEmpty;
+ shouldBeEmpty;
shouldBeEmpty = Sets.difference(toMatch, expected); shouldBeEmpty = Sets.difference(toMatch, expected);
assert shouldBeEmpty.size() == 0 : "toMatch has more keys than expected. extras: " assert shouldBeEmpty.size() == 0 : "toMatch has more keys than expected. extras: " + shouldBeEmpty;
+ shouldBeEmpty;
assertEquals(Sets.newTreeSet(toMatch), Sets.newTreeSet(expected)); assertEquals(Sets.newTreeSet(toMatch), Sets.newTreeSet(expected));
} }
}); });
} }
protected void assertConsistencyAwareRemoveEquals(final Map<String, V> map, final String key, protected void assertConsistencyAwareRemoveEquals(final Map<String, V> map, final String key, final Object equals)
final Object equals) throws InterruptedException { throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
assertEquals(map.remove(key), equals); 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, protected void assertConsistencyAwareGetEquals(final Map<String, V> map, final String key, final Object equals)
final Object equals) throws InterruptedException { throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
assertEquals(map.get(key), equals); 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) protected void assertConsistencyAwareKeySize(final Map<String, V> map, final int size) throws InterruptedException {
throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
assertEquals(map.keySet().size(), size); assertEquals(map.keySet().size(), size);
@ -275,8 +264,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
}); });
} }
protected void assertConsistencyAwareContainsKey(final Map<String, V> map) protected void assertConsistencyAwareContainsKey(final Map<String, V> map) throws InterruptedException {
throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
assert map.containsKey("one"); assert map.containsKey("one");
@ -284,8 +272,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
}); });
} }
protected void assertConsistencyAwareDoesntContainKey(final Map<String, V> map) protected void assertConsistencyAwareDoesntContainKey(final Map<String, V> map) throws InterruptedException {
throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
assert !map.containsKey("one"); assert !map.containsKey("one");
@ -306,8 +293,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
} }
} }
protected void assertConsistencyAwareNotEmpty(final Map<String, V> map) protected void assertConsistencyAwareNotEmpty(final Map<String, V> map) throws InterruptedException {
throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
assert !map.isEmpty(); 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) abstract protected void putStringWithMD5(Map<String, V> map, String key, String value) throws InterruptedException,
throws InterruptedException, ExecutionException, TimeoutException; ExecutionException, TimeoutException;
protected void fourLeftRemovingOne(Map<String, V> map) throws InterruptedException { protected void fourLeftRemovingOne(Map<String, V> map) throws InterruptedException {
map.remove("one"); map.remove("one");
assertConsistencyAwareMapSize(map, 4); assertConsistencyAwareMapSize(map, 4);
assertConsistencyAwareKeySetEquals(map, new TreeSet<String>(ImmutableSet.of("two", "three", assertConsistencyAwareKeySetEquals(map, new TreeSet<String>(ImmutableSet.of("two", "three", "four", "five")));
"four", "five")));
} }
protected void assertConsistencyAwareMapSize(final Map<String, V> map, final int size) protected void assertConsistencyAwareMapSize(final Map<String, V> map, final int size) throws InterruptedException {
throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
assertEquals(map.size(), size); assertEquals(map.size(), size);
@ -343,12 +327,10 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
} }
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public abstract void testPut() throws IOException, InterruptedException, ExecutionException, public abstract void testPut() throws IOException, InterruptedException, ExecutionException, TimeoutException;
TimeoutException;
@Test(groups = { "integration", "live" }) @Test(groups = { "integration", "live" })
public void testListContainer() throws InterruptedException, ExecutionException, public void testListContainer() throws InterruptedException, ExecutionException, TimeoutException {
TimeoutException {
String containerNameName = getContainerName(); String containerNameName = getContainerName();
try { try {
ListableMap<?, ?> map = (ListableMap<?, ?>) createMap(context, containerNameName); ListableMap<?, ?> map = (ListableMap<?, ?>) createMap(context, containerNameName);
@ -358,8 +340,8 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
} }
} }
protected void assertConsistencyAwareListContainer(final ListableMap<?, ?> map, protected void assertConsistencyAwareListContainer(final ListableMap<?, ?> map, final String containerNameName)
final String containerNameName) throws InterruptedException { throws InterruptedException {
assertConsistencyAware(new Runnable() { assertConsistencyAware(new Runnable() {
public void run() { public void run() {
assertTrue(Iterables.size(map.list()) >= 0); 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. * 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 * The singatures should match those of BoxDotNetAsyncClient, except the returnvals should not be
* wrapped in a ListenableFuture * wrapped in a Future
*/ */
String list(); String list();

View File

@ -1,7 +1,5 @@
package org.jclouds.chef; package org.jclouds.chef;
import java.util.Set;
import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Node;
import org.jclouds.chef.internal.BaseChefService; import org.jclouds.chef.internal.BaseChefService;
@ -26,11 +24,11 @@ public interface ChefService {
void deleteAllClientsAndNodesInList(Iterable<String> names); 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); void updateAutomaticAttributesOnNode(String nodeName);
} }

View File

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

View File

@ -18,8 +18,6 @@
*/ */
package org.jclouds.chef.strategy; package org.jclouds.chef.strategy;
import java.util.Set;
import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Node;
import org.jclouds.chef.strategy.internal.GetNodesImpl; import org.jclouds.chef.strategy.internal.GetNodesImpl;
@ -34,9 +32,9 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(GetNodesImpl.class) @ImplementedBy(GetNodesImpl.class)
public interface GetNodes { 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(); final Calendar expired = Calendar.getInstance();
expired.setTime(new Date()); expired.setTime(new Date());
expired.add(Calendar.SECOND, -secondsStale); 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 @Override
public boolean apply(String input) { 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.chef.strategy.DeleteAllClientsAndNodesInList;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -68,7 +68,7 @@ public class DeleteAllClientsAndNodesInListImpl implements DeleteAllClientsAndNo
@Override @Override
public void execute(Iterable<String> names) { public void execute(Iterable<String> names) {
Map<String, Exception> exceptions = newHashMap(); Map<String, Exception> exceptions = newHashMap();
Map<String, ListenableFuture<?>> responses = newHashMap(); Map<String, Future<?>> responses = newHashMap();
for (String name : names) { for (String name : names) {
responses.put(name, chefAsyncClient.deleteClient(name)); responses.put(name, chefAsyncClient.deleteClient(name));
responses.put(name, chefAsyncClient.deleteNode(name)); responses.put(name, chefAsyncClient.deleteNode(name));

View File

@ -18,17 +18,11 @@
*/ */
package org.jclouds.chef.strategy.internal; 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.Iterables.filter;
import static com.google.common.collect.Maps.newHashMap; import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
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 java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Named; import javax.inject.Named;
@ -42,8 +36,8 @@ import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.GetNodes; import org.jclouds.chef.strategy.GetNodes;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -74,39 +68,26 @@ public class GetNodesImpl implements GetNodes {
} }
@Override @Override
public Set<Node> execute() { public Iterable<? extends Node> execute() {
return execute(chefClient.listNodes()); return execute(chefClient.listNodes());
} }
@Override @Override
public Set<Node> execute(Predicate<String> nodeNameSelector) { public Iterable<? extends Node> execute(Predicate<String> nodeNameSelector) {
return execute(filter(chefClient.listNodes(), nodeNameSelector)); return execute(filter(chefClient.listNodes(), nodeNameSelector));
} }
@Override @Override
public Set<Node> execute(Iterable<String> toGet) { public Iterable<? extends Node> execute(Iterable<String> toGet) {
Map<String, Exception> exceptions = newHashMap(); return transformParallel(toGet, new Function<String, Future<Node>>() {
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() {
@Override @Override
public void run() { public Future<Node> apply(String from) {
try { return chefAsyncClient.getNode(from);
nodes.add(future.get());
} catch (InterruptedException e) {
propagate(e);
} catch (ExecutionException e) {
propagate(e);
} }
}, 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; package org.jclouds.chef.strategy.internal;
import static com.google.common.collect.Iterables.size;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.io.IOException; import java.io.IOException;
@ -69,24 +70,24 @@ public class GetNodesImplLiveTest extends BaseChefStrategyLiveTest {
@Test @Test
public void testExecute() { public void testExecute() {
assert strategy.execute().size() > 0; assert size(strategy.execute()) > 0;
} }
@Test @Test
public void testExecutePredicateOfString() { public void testExecutePredicateOfString() {
assertEquals(strategy.execute(new Predicate<String>() { assertEquals(size(strategy.execute(new Predicate<String>() {
@Override @Override
public boolean apply(String input) { public boolean apply(String input) {
return input.startsWith(prefix); return input.startsWith(prefix);
} }
}).size(), 2); })), 2);
} }
@Test @Test
public void testExecuteIterableOfString() { 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_ROLE;
import static org.jclouds.chef.reference.ChefConstants.CHEF_SERVICE_CLIENT; import static org.jclouds.chef.reference.ChefConstants.CHEF_SERVICE_CLIENT;
import java.util.Enumeration;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -41,18 +40,18 @@ import org.jclouds.chef.ChefClient;
import org.jclouds.chef.ChefContext; import org.jclouds.chef.ChefContext;
import org.jclouds.chef.ChefService; import org.jclouds.chef.ChefService;
import org.jclouds.chef.reference.ChefConstants; import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.servlet.functions.InitParamsToProperties;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.logging.jdk.JDKLogger; import org.jclouds.logging.jdk.JDKLogger;
import org.jclouds.rest.RestContextFactory; 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 * Registers a new node in Chef and binds its name to {@link ChefConstants.CHEF_NODE}, its role to
* {@link ChefConstants.CHEF_NODE}, its role to {@link ChefConstants.CHEF_ROLE} * {@link ChefConstants.CHEF_ROLE} and the {@link ChefService} for the client to
* and the {@link ChefService} for the client to * {@link ChefConstants.CHEF_SERVICE_CLIENT} upon initialized. Deletes the node and client when the
* {@link ChefConstants.CHEF_SERVICE_CLIENT} upon initialized. Deletes the node * context is destroyed.
* and client when the context is destroyed.
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@ -60,18 +59,11 @@ public class ChefRegistrationListener implements ServletContextListener {
private Logger logger = new JDKLogger.JDKLoggerFactory().getLogger(ChefRegistrationListener.class.getName()); private Logger logger = new JDKLogger.JDKLoggerFactory().getLogger(ChefRegistrationListener.class.getName());
@SuppressWarnings("unchecked")
@Override @Override
public void contextInitialized(ServletContextEvent servletContextEvent) { public void contextInitialized(ServletContextEvent servletContextEvent) {
try { try {
logger.debug("starting initialization"); logger.debug("starting initialization");
Properties overrides = new Properties(); Properties overrides = InitParamsToProperties.INSTANCE.apply(servletContextEvent);
Enumeration<String> e = servletContextEvent.getServletContext().getInitParameterNames();
while (e.hasMoreElements()) {
String propertyName = e.nextElement();
overrides.setProperty(propertyName, servletContextEvent.getServletContext().getInitParameter(propertyName));
}
String role = getInitParam(servletContextEvent, CHEF_ROLE); String role = getInitParam(servletContextEvent, CHEF_ROLE);
logger.trace("creating validator connection"); logger.trace("creating validator connection");
@ -105,8 +97,8 @@ public class ChefRegistrationListener implements ServletContextListener {
} }
private String findNextClientAndNodeName(ChefService validatorService, String prefix) { private String findNextClientAndNodeName(ChefService validatorService, String prefix) {
ListenableFuture<Set<String>> nodes = validatorService.getContext().getAsyncApi().listNodes(); Future<Set<String>> nodes = validatorService.getContext().getAsyncApi().listNodes();
ListenableFuture<Set<String>> clients = validatorService.getContext().getAsyncApi().listClients(); Future<Set<String>> clients = validatorService.getContext().getAsyncApi().listClients();
try { try {
String nodeName; String nodeName;
Set<String> names = newHashSet(concat(nodes.get(), clients.get())); 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; package org.jclouds.compute.domain;
import java.util.NoSuchElementException;
import org.jclouds.compute.internal.TemplateBuilderImpl; import org.jclouds.compute.internal.TemplateBuilderImpl;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
@ -73,6 +75,9 @@ public interface TemplateBuilder {
/** /**
* Configure this template to start in a specific location * Configure this template to start in a specific location
*
* @throws NoSuchElementException
* if location matches the id specified
*/ */
TemplateBuilder locationId(String locationId); 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 com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.installNewCredentials; import static org.jclouds.compute.util.ComputeServiceUtils.installNewCredentials;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion; 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.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.Resource; 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.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; 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, ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy, RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider, 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("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.context = checkNotNull(context, "context"); this.context = checkNotNull(context, "context");
@ -151,8 +153,7 @@ public class BaseComputeService implements ComputeService {
.getProviderId(), template.getOptions()); .getProviderId(), template.getOptions());
Set<NodeMetadata> nodes = Sets.newHashSet(); Set<NodeMetadata> nodes = Sets.newHashSet();
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap(); Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, template, nodes, Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, template, nodes, badNodes);
badNodes);
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "starting nodes"); Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "starting nodes");
if (executionExceptions.size() > 0 || badNodes.size() > 0) { if (executionExceptions.size() > 0 || badNodes.size() > 0) {
throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes); throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes);
@ -195,21 +196,26 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> destroying nodes matching(%s)", filter); logger.debug(">> destroying nodes matching(%s)", filter);
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap(); Set<NodeMetadata> set = Sets.newLinkedHashSet(transformParallel(nodesMatchingFilterAndNotTerminated(filter),
final Set<NodeMetadata> destroyedNodes = Sets.newLinkedHashSet(); new Function<NodeMetadata, Future<NodeMetadata>>() {
for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() { // TODO make an async interface instead of re-wrapping
@Override @Override
public Void call() throws Exception { public Future<NodeMetadata> apply(final NodeMetadata from) {
destroyNode(node.getId()); return executor.submit(new Callable<NodeMetadata>() {
destroyedNodes.add(node);
return null; @Override
public NodeMetadata call() throws Exception {
destroyNode(from.getId());
return from;
} }
}), executor));
});
} }
awaitCompletion(responses, executor, null, logger, "destroying nodes");
logger.debug("<< destroyed"); }, executor, null, logger, "destroying nodes"));
return destroyedNodes; logger.debug("<< destroyed(%d)", set.size());
return set;
} }
private Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminated(Predicate<NodeMetadata> filter) { private Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminated(Predicate<NodeMetadata> filter) {
@ -220,9 +226,9 @@ public class BaseComputeService implements ComputeService {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Set<? extends ComputeMetadata> listNodes() { public Set<ComputeMetadata> listNodes() {
logger.debug(">> listing nodes"); 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()); logger.debug("<< list(%d)", set.size());
return set; return set;
} }
@ -234,7 +240,7 @@ public class BaseComputeService implements ComputeService {
public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) { public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) {
checkNotNull(filter, "filter"); checkNotNull(filter, "filter");
logger.debug(">> listing node details matching(%s)", 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()); logger.debug("<< list(%d)", set.size());
return set; return set;
} }
@ -298,18 +304,15 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public void rebootNodesMatching(Predicate<NodeMetadata> filter) { public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> rebooting nodes matching(%s)", filter); logger.debug(">> rebooting nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminated(filter), new Function<NodeMetadata, Future<Void>>() {
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap(); // TODO use native async
for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
@Override @Override
public Void call() throws Exception { public Future<Void> apply(NodeMetadata from) {
rebootNode(node.getId()); rebootNode(from.getId());
return null; return Futures.immediateFuture(null);
} }
}), executor));
} }, executor, null, logger, "rebooting nodes");
awaitCompletion(responses, executor, null, logger, "rebooting nodes");
logger.debug("<< rebooted"); logger.debug("<< rebooted");
} }
@ -317,8 +320,8 @@ public class BaseComputeService implements ComputeService {
* {@inheritDoc} * {@inheritDoc}
*/ */
@Override @Override
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
Payload runScript) throws RunScriptOnNodesException { throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE); return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
} }
@ -328,18 +331,18 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
final Payload runScript, @Nullable final RunScriptOptions options) throws RunScriptOnNodesException { final Payload runScript, @Nullable final RunScriptOptions options) throws RunScriptOnNodesException {
Iterable<? extends NodeMetadata> nodes = verifyParametersAndListNodes(filter, runScript, Iterable<NodeMetadata> nodes = verifyParametersAndListNodes(filter, runScript, (options != null) ? options
(options != null) ? options : RunScriptOptions.NONE); : RunScriptOptions.NONE);
final Map<NodeMetadata, ExecResponse> execs = Maps.newHashMap(); final Map<NodeMetadata, ExecResponse> execs = Maps.newHashMap();
final Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap(); 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) { for (final NodeMetadata node : nodes) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() { responses.put(node, executor.submit(new Callable<Void>() {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
try { try {
@ -363,7 +366,7 @@ public class BaseComputeService implements ComputeService {
} }
return null; return null;
} }
}), executor)); }));
} }
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger, "starting nodes"); 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, private Iterable<NodeMetadata> verifyParametersAndListNodes(Predicate<NodeMetadata> filter, Payload runScript,
Payload runScript, final RunScriptOptions options) { final RunScriptOptions options) {
checkNotNull(filter, "Filter must be provided"); checkNotNull(filter, "Filter must be provided");
checkNotNull(runScript, "The script (represented by bytes array - use \"script\".getBytes() must be provided"); checkNotNull(runScript, "The script (represented by bytes array - use \"script\".getBytes() must be provided");
checkNotNull(options, "options"); checkNotNull(options, "options");
Iterable<? extends NodeMetadata> nodes = Iterables.filter(detailsOnAllNodes(), filter); Iterable<? extends NodeMetadata> nodes = Iterables.filter(detailsOnAllNodes(), filter);
// TODO parallel
return Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() { return Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() {
@Override @Override
@ -405,8 +408,8 @@ public class BaseComputeService implements ComputeService {
}); });
} }
private Iterable<? extends NodeMetadata> detailsOnAllNodes() { private Set<? extends NodeMetadata> detailsOnAllNodes() {
return listNodesStrategy.listDetailsOnNodesMatching(NodePredicates.all()); return Sets.newLinkedHashSet(listNodesStrategy.listDetailsOnNodesMatching(NodePredicates.all()));
} }
@Override @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.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and; import static com.google.common.base.Predicates.and;
import static com.google.common.collect.Iterables.filter; 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 com.google.common.collect.Lists.newArrayList;
import static org.jclouds.util.Utils.multiMax; import static org.jclouds.util.Utils.multiMax;
@ -79,7 +78,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@VisibleForTesting @VisibleForTesting
protected Architecture arch; protected Architecture arch;
@VisibleForTesting @VisibleForTesting
protected String locationId; protected Location location;
@VisibleForTesting @VisibleForTesting
protected String imageId; protected String imageId;
@VisibleForTesting @VisibleForTesting
@ -115,12 +114,20 @@ public class TemplateBuilderImpl implements TemplateBuilder {
this.defaultTemplateProvider = defaultTemplateProvider; 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>() { private final Predicate<ComputeMetadata> locationPredicate = new Predicate<ComputeMetadata>() {
@Override @Override
public boolean apply(ComputeMetadata input) { public boolean apply(ComputeMetadata input) {
boolean returnVal = true; boolean returnVal = true;
if (locationId != null && input.getLocation() != null) if (location != null && input.getLocation() != null)
returnVal = locationId.equals(input.getLocation().getId()); returnVal = location.equals(input.getLocation()) || location.getParent() != null
&& location.getParent().equals(input.getLocation());
return returnVal; return returnVal;
} }
}; };
@ -286,7 +293,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@Override @Override
public TemplateBuilder fromSize(Size size) { public TemplateBuilder fromSize(Size size) {
if (size.getLocation() != null) if (size.getLocation() != null)
this.locationId = size.getLocation().getId(); this.location = size.getLocation();
this.minCores = size.getCores(); this.minCores = size.getCores();
this.minRam = size.getRam(); this.minRam = size.getRam();
return this; return this;
@ -298,7 +305,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@Override @Override
public TemplateBuilder fromImage(Image image) { public TemplateBuilder fromImage(Image image) {
if (image.getLocation() != null) if (image.getLocation() != null)
this.locationId = image.getLocation().getId(); this.location = image.getLocation();
if (image.getOsFamily() != null) if (image.getOsFamily() != null)
this.os = image.getOsFamily(); this.os = image.getOsFamily();
if (image.getName() != null) if (image.getName() != null)
@ -346,7 +353,14 @@ public class TemplateBuilderImpl implements TemplateBuilder {
*/ */
@Override @Override
public TemplateBuilder locationId(final String locationId) { 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; return this;
} }
@ -379,12 +393,11 @@ public class TemplateBuilderImpl implements TemplateBuilder {
defaultTemplate.options(options); defaultTemplate.options(options);
return defaultTemplate.build(); return defaultTemplate.build();
} }
if (locationId == null) if (location == null)
locationId = defaultLocation.getId(); location = defaultLocation;
if (options == null) if (options == null)
options = optionsProvider.get(); options = optionsProvider.get();
logger.debug(">> searching params(%s)", this); logger.debug(">> searching params(%s)", this);
Location location = resolveLocation();
Size size = resolveSize(sizeSorter(), getImages()); Size size = resolveSize(sizeSorter(), getImages());
Image image = resolveImage(size); Image image = resolveImage(size);
logger.debug("<< matched image(%s)", image); logger.debug("<< matched image(%s)", image);
@ -394,19 +407,6 @@ public class TemplateBuilderImpl implements TemplateBuilder {
return new TemplateImpl(image, size, location, options); 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) { protected Size resolveSize(Ordering<Size> sizeOrdering, final Iterable<? extends Image> images) {
Size size; Size size;
try { try {
@ -429,7 +429,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
}); });
size = sizeOrdering.max(filter(sizesThatAreCompatibleWithOurImages, sizePredicate)); size = sizeOrdering.max(filter(sizesThatAreCompatibleWithOurImages, sizePredicate));
} catch (NoSuchElementException exception) { } 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); logger.debug("<< matched size(%s)", size);
return size; return size;
@ -468,7 +469,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
logger.trace("<< best images(%s)", maxImages); logger.trace("<< best images(%s)", maxImages);
return maxImages.get(maxImages.size() - 1); return maxImages.get(maxImages.size() - 1);
} catch (NoSuchElementException exception) { } 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 @VisibleForTesting
boolean nothingChangedExceptOptions() { 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 && osDescription == null && imageVersion == null && imageName == null && imageDescription == null
&& minCores == 0 && minRam == 0 && !biggest && !fastest; && minCores == 0 && minRam == 0 && !biggest && !fastest;
} }
@ -625,7 +627,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
public String toString() { public String toString() {
return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest + ", imageName=" + imageName return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest + ", imageName=" + imageName
+ ", imageDescription=" + imageDescription + ", imageId=" + imageId + ", imageVersion=" + imageVersion + ", 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 + "]"; + ", 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.domain.Template;
import org.jclouds.compute.strategy.impl.EncodeTagIntoNameRunNodesAndAddToSetStrategy; import org.jclouds.compute.strategy.impl.EncodeTagIntoNameRunNodesAndAddToSetStrategy;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
import com.google.inject.ImplementedBy; import com.google.inject.ImplementedBy;
/** /**
@ -37,6 +37,6 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(EncodeTagIntoNameRunNodesAndAddToSetStrategy.class) @ImplementedBy(EncodeTagIntoNameRunNodesAndAddToSetStrategy.class)
public interface RunNodesAndAddToSetStrategy { 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); Set<NodeMetadata> nodes, Map<NodeMetadata, Exception> badNodes);
} }

View File

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

View File

@ -180,12 +180,12 @@ public class StubComputeServiceContextModule extends AbstractModule {
private NodeState state; private NodeState state;
private final ExecutorService service; private final ExecutorService service;
public StubNodeMetadata(String providerId, String name, String id, Location location, public StubNodeMetadata(String providerId, String name, String id, Location location, URI uri,
URI uri, Map<String, String> userMetadata, String tag, Image image, NodeState state, Map<String, String> userMetadata, String tag, Image image, NodeState state,
Iterable<String> publicAddresses, Iterable<String> privateAddresses, Iterable<String> publicAddresses, Iterable<String> privateAddresses, Map<String, String> extra,
Map<String, String> extra, Credentials credentials, ExecutorService service) { Credentials credentials, ExecutorService service) {
super(providerId, name, id, location, uri, userMetadata, tag, image, state, super(providerId, name, id, location, uri, userMetadata, tag, image, state, publicAddresses, privateAddresses,
publicAddresses, privateAddresses, extra, credentials); extra, credentials);
this.setState(state, 0); this.setState(state, 0);
this.service = service; this.service = service;
} }
@ -227,12 +227,10 @@ public class StubComputeServiceContextModule extends AbstractModule {
private final String passwordPrefix; private final String passwordPrefix;
@Inject @Inject
public StubAddNodeWithTagStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes, public StubAddNodeWithTagStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes, Location location,
Location location, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
@Named("NODE_ID") Provider<Integer> idProvider, @Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
@Named("PUBLIC_IP_PREFIX") String publicIpPrefix, @Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix) {
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix,
@Named("PASSWORD_PREFIX") String passwordPrefix) {
this.nodes = nodes; this.nodes = nodes;
this.location = location; this.location = location;
this.service = Executors.newCachedThreadPool(); this.service = Executors.newCachedThreadPool();
@ -244,14 +242,12 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Override @Override
public NodeMetadata execute(String tag, String name, Template template) { public NodeMetadata execute(String tag, String name, Template template) {
checkArgument(location.equals(template.getLocation()), "invalid location: " checkArgument(location.equals(template.getLocation()), "invalid location: " + template.getLocation());
+ template.getLocation());
int id = idProvider.get(); int id = idProvider.get();
StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "", location, null, StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "", location, null, ImmutableMap
ImmutableMap.<String, String> of(), tag, template.getImage(), NodeState.PENDING, .<String, String> of(), tag, template.getImage(), NodeState.PENDING, ImmutableSet
ImmutableSet.<String> of(publicIpPrefix + id), ImmutableSet .<String> of(publicIpPrefix + id), ImmutableSet.<String> of(privateIpPrefix + id), ImmutableMap
.<String> of(privateIpPrefix + id), ImmutableMap.<String, String> of(), .<String, String> of(), new Credentials("root", passwordPrefix + id), service);
new Credentials("root", passwordPrefix + id), service);
nodes.put(id, node); nodes.put(id, node);
node.setState(NodeState.RUNNING, 100); node.setState(NodeState.RUNNING, 100);
return node; return node;
@ -289,8 +285,7 @@ public class StubComputeServiceContextModule extends AbstractModule {
} }
@Override @Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching( public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
Predicate<ComputeMetadata> filter) {
return Iterables.filter(nodes.values(), filter); return Iterables.filter(nodes.values(), filter);
} }
} }
@ -363,18 +358,16 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Size> provideSizes() { protected Set<? extends Size> provideSizes() {
return ImmutableSet.of(new StubSize("small", 1, 1740, 160, ImmutableSet return ImmutableSet.<Size> of(new StubSize("small", 1, 1740, 160, ImmutableSet.of(Architecture.X86_32)),
.of(Architecture.X86_32)), new StubSize("medium", 4, 7680, 850, ImmutableSet new StubSize("medium", 4, 7680, 850, ImmutableSet.of(Architecture.X86_64)), new StubSize("large", 8,
.of(Architecture.X86_64)), new StubSize("large", 8, 15360, 1690, ImmutableSet 15360, 1690, ImmutableSet.of(Architecture.X86_64)));
.of(Architecture.X86_64)));
} }
private static class StubSize extends org.jclouds.compute.domain.internal.SizeImpl { private static class StubSize extends org.jclouds.compute.domain.internal.SizeImpl {
/** The serialVersionUID */ /** The serialVersionUID */
private static final long serialVersionUID = -1842135761654973637L; private static final long serialVersionUID = -1842135761654973637L;
StubSize(String type, int cores, int ram, int disk, StubSize(String type, int cores, int ram, int disk, Iterable<Architecture> supportedArchitectures) {
Iterable<Architecture> supportedArchitectures) {
super(type, type, type, null, null, ImmutableMap.<String, String> of(), cores, ram, disk, super(type, type, type, null, null, ImmutableMap.<String, String> of(), cores, ram, disk,
architectureIn(supportedArchitectures)); architectureIn(supportedArchitectures));
} }
@ -383,14 +376,14 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected Set<? extends Image> provideImages(Location defaultLocation) { protected Set<? extends Image> provideImages(Location defaultLocation) {
return ImmutableSet.of(new ImageImpl("1", OsFamily.UBUNTU.name(), "1", defaultLocation, null, String parentId = defaultLocation.getParent().getId();
ImmutableMap.<String, String> of(), "stub ubuntu 32", "", OsFamily.UBUNTU, return ImmutableSet.<Image> of(new ImageImpl("1", OsFamily.UBUNTU.name(), parentId + "/1", defaultLocation
"ubuntu 64", Architecture.X86_64, new Credentials("root", null)), new ImageImpl("2", .getParent(), null, ImmutableMap.<String, String> of(), "stub ubuntu 32", "", OsFamily.UBUNTU,
OsFamily.UBUNTU.name(), "2", defaultLocation, null, ImmutableMap "ubuntu 64", Architecture.X86_64, new Credentials("root", null)), new ImageImpl("2", OsFamily.UBUNTU
.<String, String> of(), "stub ubuntu 64", "", OsFamily.UBUNTU, "ubuntu 64", .name(), parentId + "/2", defaultLocation.getParent(), null, ImmutableMap.<String, String> of(),
Architecture.X86_64, new Credentials("root", null)), new ImageImpl("3", "stub ubuntu 64", "", OsFamily.UBUNTU, "ubuntu 64", Architecture.X86_64, new Credentials("root", null)),
OsFamily.CENTOS.name(), "3", defaultLocation, null, ImmutableMap new ImageImpl("3", OsFamily.CENTOS.name(), parentId + "/3", defaultLocation.getParent(), null,
.<String, String> of(), "stub centos 64", "", OsFamily.CENTOS, "centos 64", ImmutableMap.<String, String> of(), "stub centos 64", "", OsFamily.CENTOS, "centos 64",
Architecture.X86_64, new Credentials("root", null))); Architecture.X86_64, new Credentials("root", null)));
} }
@ -398,7 +391,8 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Singleton @Singleton
Location getLocation(@org.jclouds.rest.annotations.Provider String providerName) { Location getLocation(@org.jclouds.rest.annotations.Provider String providerName) {
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null); 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 @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.installNewCredentials;
import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth; import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion; import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -31,6 +30,7 @@ import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable; 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.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable; import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket; 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.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject; import com.google.inject.Inject;
/** /**
@ -84,8 +82,9 @@ public class ComputeUtils {
@Inject @Inject
public ComputeUtils(Predicate<IPSocket> socketTester, public ComputeUtils(Predicate<IPSocket> socketTester,
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning, GetNodeMetadataStrategy getNode, @Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
Timeouts timeouts, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, GetNodeMetadataStrategy getNode, Timeouts timeouts,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) { @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.nodeRunning = nodeRunning; this.nodeRunning = nodeRunning;
this.timeouts = timeouts; this.timeouts = timeouts;
@ -95,19 +94,20 @@ public class ComputeUtils {
this.executor = executor; this.executor = executor;
} }
public Map<?, ListenableFuture<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap( public Map<?, Future<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options,
final TemplateOptions options, Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes, Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
final Map<NodeMetadata, Exception> badNodes) { final Map<NodeMetadata, Exception> badNodes) {
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap(); Map<NodeMetadata, Future<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : runningNodes) { for (final NodeMetadata node : runningNodes) {
responses.put(node, makeListenable(executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap( responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes,
node, badNodes, goodNodes, options)), executor)); goodNodes, options)));
} }
return responses; return responses;
} }
public Callable<Void> runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(final NodeMetadata node, 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>() { return new Callable<Void>() {
@Override @Override
public Void call() throws Exception { public Void call() throws Exception {
@ -190,11 +190,12 @@ public class ComputeUtils {
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false); 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) { @Nullable SshCallable<?> last) {
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured"); checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
checkNodeHasPublicIps(node); 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); SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
try { try {
ssh.connect(); ssh.connect();
@ -205,8 +206,8 @@ public class ComputeUtils {
} }
} }
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<? extends SshCallable<?>> parallel, private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<SshCallable<?>> parallel, SshCallable<?> last,
SshCallable<?> last, SshClient ssh) { SshClient ssh) {
Map<SshCallable<?>, Object> responses = Maps.newHashMap(); Map<SshCallable<?>, Object> responses = Maps.newHashMap();
if (Iterables.size(parallel) > 0) { if (Iterables.size(parallel) > 0) {
responses.putAll(runCallablesUsingSshClient(parallel, ssh)); responses.putAll(runCallablesUsingSshClient(parallel, ssh));
@ -231,13 +232,13 @@ public class ComputeUtils {
return ssh; return ssh;
} }
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<? extends SshCallable<?>> parallel, // TODO refactor
SshClient ssh) { private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<SshCallable<?>> parallel, SshClient ssh) {
Map<SshCallable<?>, ListenableFuture<?>> parallelResponses = Maps.newHashMap(); Map<SshCallable<?>, Future<?>> parallelResponses = Maps.newHashMap();
for (SshCallable<?> callable : parallel) { for (SshCallable<?> callable : parallel) {
callable.setConnection(ssh, logger); 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"); Map<SshCallable<?>, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, logger, "ssh");
@ -248,9 +249,9 @@ public class ComputeUtils {
} }
@SuppressWarnings("unchecked") @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(); Map<SshCallable<?>, T> actualResponses = Maps.newHashMap();
for (Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses.entrySet()) { for (Map.Entry<SshCallable<?>, Future<?>> entry : responses.entrySet()) {
try { try {
actualResponses.put(entry.getKey(), (T) entry.getValue().get()); actualResponses.put(entry.getKey(), (T) entry.getValue().get());
} catch (InterruptedException e) { } 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.get;
import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Sets.filter; 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 com.google.common.collect.Sets.newTreeSet;
import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideCredentialsWith; import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideCredentialsWith;
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED; import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
@ -197,8 +197,8 @@ public abstract class BaseComputeServiceLiveTest {
try { try {
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options); Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
Credentials good = nodes.iterator().next().getCredentials(); Credentials good = nodes.iterator().next().getCredentials();
assert good.identity != null; assert good.identity != null : nodes;
assert good.credential != null; assert good.credential != null : nodes;
Image image = get(nodes, 0).getImage(); Image image = get(nodes, 0).getImage();
try { try {
@ -336,8 +336,9 @@ public abstract class BaseComputeServiceLiveTest {
.append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n") .append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append( .append(
"echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n") "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( .append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
"yum --nogpgcheck -y install java-1.6.0-openjdk\n").append( .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") "echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n")
.toString(); .toString();
default: default:
@ -347,8 +348,8 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired") @Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception { public void testGet() throws Exception {
Set<? extends NodeMetadata> metadataSet = newHashSet(filter(client.listNodesDetailsMatching(all()), and( Set<? extends NodeMetadata> nodes = client.listNodesDetailsMatching(all());
withTag(tag), not(TERMINATED)))); Set<? extends NodeMetadata> metadataSet = newLinkedHashSet(filter(nodes, and(withTag(tag), not(TERMINATED))));
for (NodeMetadata node : nodes) { for (NodeMetadata node : nodes) {
metadataSet.remove(node); metadataSet.remove(node);
NodeMetadata metadata = client.getNodeMetadata(node.getId()); NodeMetadata metadata = client.getNodeMetadata(node.getId());

View File

@ -32,6 +32,8 @@ import java.io.IOException;
import java.io.Serializable; import java.io.Serializable;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.easymock.IArgumentMatcher; import org.easymock.IArgumentMatcher;
import org.jclouds.compute.domain.Architecture; import org.jclouds.compute.domain.Architecture;
@ -86,7 +88,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
Template defaultTemplate = client.templateBuilder().build(); Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getArchitecture(), Architecture.X86_64); assertEquals(defaultTemplate.getImage().getArchitecture(), Architecture.X86_64);
assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.UBUNTU); assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), provider); assertEquals(defaultTemplate.getLocation().getId(), provider + "zone");
assertEquals(defaultTemplate.getSize().getCores(), 4.0d); assertEquals(defaultTemplate.getSize().getCores(), 4.0d);
} }
@ -361,4 +363,9 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
super.testTemplateMatch(); 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); Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
expect(optionsProvider.get()).andReturn(new TemplateOptions()); expect(optionsProvider.get()).andReturn(new TemplateOptions());
expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce(); expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce();
@ -163,7 +162,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
expect(optionsProvider.get()).andReturn(new TemplateOptions()); expect(optionsProvider.get()).andReturn(new TemplateOptions());
expect(image.getId()).andReturn("imageId").atLeastOnce(); expect(image.getId()).andReturn("imageId").atLeastOnce();
expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce(); expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce();
@ -208,7 +206,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class); TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
expect(optionsProvider.get()).andReturn(new TemplateOptions()); expect(optionsProvider.get()).andReturn(new TemplateOptions());
expect(image.getId()).andReturn("notImageId").atLeastOnce(); expect(image.getId()).andReturn("notImageId").atLeastOnce();
@ -321,8 +318,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateOptions defaultOptions = createMock(TemplateOptions.class); TemplateOptions defaultOptions = createMock(TemplateOptions.class);
expect(optionsProvider.get()).andReturn(defaultOptions);
replay(defaultOptions); replay(defaultOptions);
replay(defaultLocation); replay(defaultLocation);
replay(optionsProvider); replay(optionsProvider);
@ -390,7 +385,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateOptions defaultOptions = createMock(TemplateOptions.class); TemplateOptions defaultOptions = createMock(TemplateOptions.class);
expect(defaultLocation.getId()).andReturn("foo");
expect(optionsProvider.get()).andReturn(defaultOptions); expect(optionsProvider.get()).andReturn(defaultOptions);
replay(defaultOptions); replay(defaultOptions);
@ -402,7 +396,7 @@ public class TemplateBuilderImplTest {
templateBuilderProvider); templateBuilderProvider);
try { try {
template.imageId("foo").build(); template.imageId("region/ami").build();
assert false; assert false;
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
@ -430,18 +424,9 @@ public class TemplateBuilderImplTest {
TemplateOptions from = provideTemplateOptions(); TemplateOptions from = provideTemplateOptions();
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class); 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(from);
// expect(optionsProvider.get()).andReturn(provideTemplateOptions());
expect(from.getInboundPorts()).andReturn(new int[] { 22 }); 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(defaultLocation);
replay(optionsProvider); replay(optionsProvider);
@ -451,7 +436,7 @@ public class TemplateBuilderImplTest {
templateBuilderProvider); templateBuilderProvider);
try { try {
template.imageId("foo").options(provideTemplateOptions()).build(); template.imageId("region/ami").options(provideTemplateOptions()).build();
assert false; assert false;
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {

View File

@ -18,41 +18,111 @@
*/ */
package org.jclouds.concurrent; 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;
import java.util.Map.Entry; import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; 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.Nullable;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.ForwardingObject;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ExecutionList; import com.google.common.util.concurrent.ExecutionList;
import com.google.common.util.concurrent.ForwardingFuture; 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.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 * @author Adrian Cole
*/ */
@Singleton @Singleton
public class ConcurrentUtils { public class ConcurrentUtils {
@Resource
private static Logger logger = Logger.CONSOLE;
public static <T> Map<T, Exception> awaitCompletion(Map<T, ? extends ListenableFuture<?>> responses, @Inject(optional = true)
ExecutorService executor, @Nullable Long maxTime, final Logger logger, final String logPrefix) { @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) if (responses.size() == 0)
return ImmutableMap.of(); return ImmutableMap.of();
final int total = responses.size(); final int total = responses.size();
@ -61,8 +131,8 @@ public class ConcurrentUtils {
final AtomicInteger errors = new AtomicInteger(0); final AtomicInteger errors = new AtomicInteger(0);
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
final Map<T, Exception> errorMap = Maps.newHashMap(); final Map<T, Exception> errorMap = Maps.newHashMap();
for (final Entry<T, ? extends ListenableFuture<?>> future : responses.entrySet()) { for (final java.util.Map.Entry<T, ? extends Future<?>> future : responses.entrySet()) {
future.getValue().addListener(new Runnable() { makeListenable(future.getValue(), exec).addListener(new Runnable() {
public void run() { public void run() {
try { try {
future.getValue().get(); future.getValue().get();
@ -74,7 +144,7 @@ public class ConcurrentUtils {
} }
doneSignal.countDown(); doneSignal.countDown();
} }
}, executor); }, exec);
} }
try { try {
if (maxTime != null) if (maxTime != null)
@ -99,6 +169,22 @@ public class ConcurrentUtils {
return errorMap; 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, private static void logException(Logger logger, String logPrefix, int total, int complete, int errors, long start,
Exception e) { Exception e) {
String message = message(logPrefix, total, complete, errors, start); String message = message(logPrefix, total, complete, errors, start);
@ -123,49 +209,55 @@ public class ConcurrentUtils {
if (future instanceof ListenableFuture<?>) { if (future instanceof ListenableFuture<?>) {
return (ListenableFuture<T>) future; 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. * Just like {@code Futures#compose} except that we check the type of the executorService before
* <p/> * creating the Future. If we are single threaded, invoke the function lazy as opposed to
* Temporary hack until http://code.google.com/p/guava-libraries/issues/detail?id=317 is fixed. * 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; public static class FutureListener<T> {
private final Future<T> future;
// The execution list to hold our listeners. private final ExecutorService executor;
private final ExecutionList executionList = new ExecutionList(); 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); private final AtomicBoolean hasListeners = new AtomicBoolean(false);
// The delegate future. static <T> FutureListener<T> create(Future<T> future, ExecutorService executor) {
private final Future<T> delegate; return new FutureListener<T>(future, executor);
ListenableFutureAdapter(ExecutorService executorService, final Future<T> delegate) {
this.adapterExecutor = executorService;
this.delegate = delegate;
} }
@Override private FutureListener(Future<T> future, ExecutorService executor) {
protected Future<T> delegate() { this.future = checkNotNull(future, "future");
return delegate; this.executor = checkNotNull(executor, "executor");
} }
/* @Override */
public void addListener(Runnable listener, Executor exec) { public void addListener(Runnable listener, Executor exec) {
// When a listener is first added, we run a task that will wait for // 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)) { if (!hasListeners.get() && hasListeners.compareAndSet(false, true)) {
adapterExecutor.execute(new Runnable() { executor.execute(new Runnable() {
/* @Override */ /* @Override */
public void run() { public void run() {
try { try {
delegate.get(); future.get();
} catch (CancellationException e) { } catch (CancellationException e) {
// The task was cancelled, so it is done, run the listeners. // The task was cancelled, so it is done, run the listeners.
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -181,5 +273,289 @@ public class ConcurrentUtils {
} }
executionList.add(listener, exec); 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; package org.jclouds.concurrent;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -27,30 +29,35 @@ import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture; 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 * Temporarily here until the following is resolved: <a
* href="http://code.google.com/p/guava-libraries/issues/detail?id=310"> guava issue 310</a> * href="http://code.google.com/p/guava-libraries/issues/detail?id=310"> guava issue 310</a>
* *
* @author Adrian Cole * @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; private final Function<Exception, T> function;
public FutureExceptionParser(ListenableFuture<T> delegate, Function<Exception, T> function) { public static <T> ExceptionParsingListenableFuture<T> create(ListenableFuture<T> future,
this.delegate = delegate; Function<Exception, T> function) {
this.function = 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) { public boolean cancel(boolean mayInterruptIfRunning) {
return delegate.cancel(mayInterruptIfRunning); return future.cancel(mayInterruptIfRunning);
} }
public T get() throws InterruptedException, ExecutionException { public T get() throws InterruptedException, ExecutionException {
try { try {
return delegate.get(); return future.get();
} catch (Exception e) { } catch (Exception e) {
return attemptConvert(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); return function.apply(e instanceof ExecutionException ? (Exception) e.getCause() : e);
} }
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
TimeoutException {
try { try {
return delegate.get(timeout, unit); return future.get(timeout, unit);
} catch (Exception e) { } catch (Exception e) {
return attemptConvert(e); return attemptConvert(e);
} }
} }
public boolean isCancelled() { public boolean isCancelled() {
return delegate.isCancelled(); return future.isCancelled();
} }
public boolean isDone() { public boolean isDone() {
return delegate.isDone(); return future.isDone();
} }
@Override @Override
public void addListener(Runnable listener, Executor exec) { 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; 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 java.util.concurrent.TimeoutException;
import org.jclouds.util.Utils;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
@ -44,15 +43,15 @@ public class RetryOnTimeOutExceptionSupplier<T> implements Supplier<T> {
ex = null; ex = null;
return delegate.get(); return delegate.get();
} catch (Exception e) { } catch (Exception e) {
if ((ex = Utils.getFirstThrowableOfType(e, TimeoutException.class)) != null) if ((ex = getFirstThrowableOfType(e, TimeoutException.class)) != null)
continue; continue;
Throwables.propagate(e); propagate(e);
assert false; assert false;
return null; return null;
} }
} }
if (ex != null) if (ex != null)
Throwables.propagate(ex); propagate(ex);
assert false; assert false;
return null; return null;
} }

View File

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

View File

@ -18,7 +18,7 @@
*/ */
package org.jclouds.http; package org.jclouds.http;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
/** /**
* Capable of invoking http commands. * Capable of invoking http commands.
@ -33,7 +33,7 @@ public interface HttpCommandExecutorService {
* *
* @param command * @param command
* that generates requests * 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 java.util.concurrent.SynchronousQueue;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
/** /**
* Used for passing objects for response processing * Used for passing objects for response processing
@ -32,11 +32,11 @@ public class HttpCommandRendezvous<T> {
private final HttpCommand command; private final HttpCommand command;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private final SynchronousQueue rendezvous; private final SynchronousQueue rendezvous;
private final ListenableFuture<T> future; private final Future<T> future;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public HttpCommandRendezvous(HttpCommand command, SynchronousQueue rendezvous, public HttpCommandRendezvous(HttpCommand command, SynchronousQueue rendezvous,
ListenableFuture<T> future) { Future<T> future) {
this.command = command; this.command = command;
this.rendezvous = rendezvous; this.rendezvous = rendezvous;
this.future = future; this.future = future;
@ -53,14 +53,14 @@ public class HttpCommandRendezvous<T> {
} }
public void cancel() { public void cancel() {
getListenableFuture().cancel(true); getFuture().cancel(true);
} }
public HttpCommand getCommand() { public HttpCommand getCommand() {
return command; return command;
} }
public ListenableFuture<T> getListenableFuture() { public Future<T> getFuture() {
return future; return future;
} }

View File

@ -18,6 +18,8 @@
*/ */
package org.jclouds.http; package org.jclouds.http;
import java.util.concurrent.Future;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@ -30,7 +32,7 @@ import com.google.common.util.concurrent.ListenableFuture;
public interface TransformingHttpCommandExecutorService { 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> * @param <T>
* type that is required from the value. * type that is required from the value.

View File

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

View File

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

View File

@ -19,7 +19,6 @@
package org.jclouds.http.internal; package org.jclouds.http.internal;
import static com.google.common.io.ByteStreams.copy; 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.checkRequestHasContentLengthOrChunkedEncoding;
import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled; import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
import static org.jclouds.util.Utils.getFirstThrowableOfType; import static org.jclouds.util.Utils.getFirstThrowableOfType;
@ -29,6 +28,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -49,7 +49,6 @@ import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.io.NullOutputStream; 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(); HttpRequest request = command.getRequest();
checkRequestHasContentLengthOrChunkedEncoding(request, checkRequestHasContentLengthOrChunkedEncoding(request,
"if the request has a payload, it must be set to chunked encoding or specify a content length: " + request); "if the request has a payload, it must be set to chunked encoding or specify a content length: "
return makeListenable(ioWorkerExecutor.submit(new HttpResponseCallable(command)), ioWorkerExecutor); + request);
return ioWorkerExecutor.submit(new HttpResponseCallable(command));
} }
public class HttpResponseCallable implements Callable<HttpResponse> { public class HttpResponseCallable implements Callable<HttpResponse> {

View File

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

View File

@ -56,4 +56,9 @@ public class GsonWrapper implements Json {
return gson.toJson(src); 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 org.jclouds.rest.internal.RestContextImpl;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
import com.google.inject.ImplementedBy; 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. * 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(); A getAsyncApi();

View File

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

View File

@ -33,7 +33,7 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.concurrent.FutureExceptionParser; import org.jclouds.concurrent.ExceptionParsingListenableFuture;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponse;
import org.jclouds.http.TransformingHttpCommand; import org.jclouds.http.TransformingHttpCommand;
@ -91,14 +91,14 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
return delegateMap.get(new ClassMethodArgs(method.getReturnType(), method, args)); return delegateMap.get(new ClassMethodArgs(method.getReturnType(), method, args));
} else if (annotationProcessor.getDelegateOrNull(method) != null } else if (annotationProcessor.getDelegateOrNull(method) != null
&& ListenableFuture.class.isAssignableFrom(method.getReturnType())) { && ListenableFuture.class.isAssignableFrom(method.getReturnType())) {
return createFuture(method, args); return createListenableFuture(method, args);
} else { } else {
throw new RuntimeException("method is intended solely to set constants: " + method); throw new RuntimeException("method is intended solely to set constants: " + method);
} }
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private ListenableFuture<?> createFuture(Method method, Object[] args) throws ExecutionException { private ListenableFuture<?> createListenableFuture(Method method, Object[] args) throws ExecutionException {
method = annotationProcessor.getDelegateOrNull(method); method = annotationProcessor.getDelegateOrNull(method);
logger.trace("Converting %s.%s", declaring.getSimpleName(), method.getName()); logger.trace("Converting %s.%s", declaring.getSimpleName(), method.getName());
Function<Exception, ?> exceptionParser = annotationProcessor Function<Exception, ?> exceptionParser = annotationProcessor
@ -136,7 +136,7 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
if (exceptionParser != null) { if (exceptionParser != null) {
logger.trace("Exceptions from %s.%s are parsed by %s", declaring.getSimpleName(), method.getName(), logger.trace("Exceptions from %s.%s are parsed by %s", declaring.getSimpleName(), method.getName(),
exceptionParser.getClass().getSimpleName()); exceptionParser.getClass().getSimpleName());
result = new FutureExceptionParser(result, exceptionParser); result = new ExceptionParsingListenableFuture(result, exceptionParser);
} }
return result; 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.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.instanceOf; import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.base.Predicates.notNull; 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.getCausalChain;
import static com.google.common.base.Throwables.propagate; 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.filter;
import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get; 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.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.io.OutputSupplier; import com.google.common.io.OutputSupplier;
import com.google.inject.Module;
import com.google.inject.ProvisionException; import com.google.inject.ProvisionException;
import com.google.inject.spi.Message; 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 * Encode the given string with the given encoding, if possible. If the encoding fails with
* encoding fails with {@link UnsupportedEncodingException}, log a warning * {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
* and fall back to the system's default encoding. * encoding.
* *
* @param str * @param str
* what to encode * what to encode
* @param charsetName * @param charsetName
* the name of a supported {@link java.nio.charset.Charset * the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
* </code>charset<code>}
* @return properly encoded String. * @return properly encoded String.
*/ */
public static byte[] encodeString(String str, String charsetName) { 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 * Encode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
* very unlikely event the encoding fails with * the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
* {@link UnsupportedEncodingException}, log a warning and fall back to the * the system's default encoding.
* system's default encoding.
* *
* @param str * @param str
* what to encode * what to encode
@ -317,8 +319,7 @@ public class Utils {
} }
/** /**
* Will throw an exception if the argument is null or empty. Accepts a custom * Will throw an exception if the argument is null or empty. Accepts a custom error message.
* error message.
* *
* @param nullableString * @param nullableString
* string to verify. Can be null or empty. * 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 * Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
* (supported-clouds). Uses rest.properties to populate the set. * rest.properties to populate the set.
* *
*/ */
public static Iterable<String> getSupportedProviders() { public static Iterable<String> getSupportedProviders() {
@ -339,8 +340,8 @@ public class Utils {
} }
/** /**
* Gets a set of supported providers. Idea stolen from pallets * Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
* (supported-clouds). Uses rest.properties to populate the set. * rest.properties to populate the set.
* *
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -430,4 +431,37 @@ public class Utils {
return PropertiesBuilder.class; 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; 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 java.util.concurrent.Executors.newCachedThreadPool;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion; import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.FuturesTestingUtils.CALLABLE_DURATION; import static org.jclouds.concurrent.FuturesTestingUtils.CALLABLE_DURATION;
@ -35,7 +35,7 @@ import java.util.concurrent.ExecutorService;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.util.concurrent.ListenableFuture; import java.util.concurrent.Future;
/** /**
* Tests behavior of ConcurrentUtils * Tests behavior of ConcurrentUtils
@ -54,7 +54,7 @@ public class ConcurrentUtilsTest {
ExecutorService chainExecutor = sameThreadExecutor(); ExecutorService chainExecutor = sameThreadExecutor();
long start = System.currentTimeMillis(); 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); checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
} }
@ -68,7 +68,7 @@ public class ConcurrentUtilsTest {
ExecutorService chainExecutor = sameThreadExecutor(); ExecutorService chainExecutor = sameThreadExecutor();
long start = System.currentTimeMillis(); 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, Map<String, Exception> exceptions = awaitCompletion(responses, sameThreadExecutor(), null, Logger.CONSOLE,
"test same thread"); "test same thread");
assertEquals(exceptions.size(), 0); assertEquals(exceptions.size(), 0);

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