Issue 109: changed existing behavior to use strategy pattern

git-svn-id: http://jclouds.googlecode.com/svn/trunk@1944 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-10-04 00:26:37 +00:00
parent f78670f871
commit 16de6c839c
13 changed files with 708 additions and 213 deletions

View File

@ -141,8 +141,8 @@ public abstract class BlobStoreContextBuilder<S extends BlobStore<C, M, B>, C ex
this.containerMetadataType = containerMetadataType;
this.blobMetadataType = blobMetadataType;
this.blobType = blobType;
modules.add(new BlobStoreMapsModule<S, C, M, B>(connectionType,
containerMetadataType, blobMetadataType, blobType));
modules.add(BlobStoreMapsModule.Builder.newBuilder(connectionType,
containerMetadataType, blobMetadataType, blobType).build());
}
@SuppressWarnings("unchecked")

View File

@ -23,15 +23,18 @@
*/
package org.jclouds.blobstore;
import javax.inject.Inject;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.internal.BlobMapImpl;
import org.jclouds.blobstore.internal.InputStreamMapImpl;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.blobstore.strategy.internal.ContainerListGetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.internal.RetryOnNotFoundGetAllBlobsStrategy;
import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.util.Types;
@ -39,42 +42,134 @@ import com.google.inject.util.Types;
/**
* @author Adrian Cole
*/
public class BlobStoreMapsModule<S extends BlobStore<C, M, B>, C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>>
extends AbstractModule {
public class BlobStoreMapsModule extends AbstractModule {
@SuppressWarnings("unchecked")
private BlobStoreMapsModule(TypeLiteral blobMapFactoryType, TypeLiteral blobMapImplType,
TypeLiteral inputStreamMapFactoryType, TypeLiteral inputStreamMapImplType,
TypeLiteral getAllBlobsStrategyType, TypeLiteral getAllBlobsStrategyImplType,
TypeLiteral getAllBlobMetadataStrategyType,
TypeLiteral getAllBlobMetadataStrategyImplType) {
this.blobMapFactoryType = blobMapFactoryType;
this.blobMapImplType = blobMapImplType;
this.inputStreamMapFactoryType = inputStreamMapFactoryType;
this.inputStreamMapImplType = inputStreamMapImplType;
this.getAllBlobsStrategyType = getAllBlobsStrategyType;
this.getAllBlobsStrategyImplType = getAllBlobsStrategyImplType;
this.getAllBlobMetadataStrategyType = getAllBlobMetadataStrategyType;
this.getAllBlobMetadataStrategyImplType = getAllBlobMetadataStrategyImplType;
}
// code is unchecked here as we are getting types at runtime. Due to type erasure, we cannot pass
// generic types into provider methods. This is why we are sending in TypeLiterals.
@SuppressWarnings("unchecked")
private final TypeLiteral blobMapFactoryType;
protected final TypeLiteral blobMapFactoryType;
@SuppressWarnings("unchecked")
private final TypeLiteral blobMapImplType;
protected final TypeLiteral blobMapImplType;
@SuppressWarnings("unchecked")
private final TypeLiteral inputStreamMapFactoryType;
protected final TypeLiteral inputStreamMapFactoryType;
@SuppressWarnings("unchecked")
private final TypeLiteral inputStreamMapImplType;
protected final TypeLiteral inputStreamMapImplType;
@SuppressWarnings("unchecked")
protected final TypeLiteral getAllBlobsStrategyType;
@SuppressWarnings("unchecked")
protected final TypeLiteral getAllBlobsStrategyImplType;
@SuppressWarnings("unchecked")
protected final TypeLiteral getAllBlobMetadataStrategyType;
@SuppressWarnings("unchecked")
protected final TypeLiteral getAllBlobMetadataStrategyImplType;
@Inject
public BlobStoreMapsModule(TypeLiteral<S> connectionType, TypeLiteral<C> containerMetadataType,
TypeLiteral<M> blobMetadataType, TypeLiteral<B> blobType) {
blobMapFactoryType = TypeLiteral.get(Types.newParameterizedTypeWithOwner(BlobMap.class,
BlobMap.Factory.class, blobMetadataType.getType(), blobType.getType()));
blobMapImplType = TypeLiteral.get(Types.newParameterizedType(BlobMapImpl.class,
connectionType.getType(), containerMetadataType.getType(), blobMetadataType
.getType(), blobType.getType()));
inputStreamMapFactoryType = TypeLiteral.get(Types.newParameterizedTypeWithOwner(
InputStreamMap.class, InputStreamMap.Factory.class, blobMetadataType.getType()));
inputStreamMapImplType = TypeLiteral.get(Types.newParameterizedType(InputStreamMapImpl.class,
connectionType.getType(), containerMetadataType.getType(), blobMetadataType
.getType(), blobType.getType()));
public static class Builder<S extends BlobStore<C, M, B>, C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> {
@SuppressWarnings("unused")
private final TypeLiteral<S> connectionType;
private final TypeLiteral<C> containerMetadataType;
private final TypeLiteral<M> blobMetadataType;
private final TypeLiteral<B> blobType;
@SuppressWarnings("unchecked")
private TypeLiteral blobMapFactoryType;
@SuppressWarnings("unchecked")
private TypeLiteral blobMapImplType;
@SuppressWarnings("unchecked")
private TypeLiteral inputStreamMapFactoryType;
@SuppressWarnings("unchecked")
private TypeLiteral inputStreamMapImplType;
@SuppressWarnings("unchecked")
private TypeLiteral getAllBlobsStrategyType;
@SuppressWarnings("unchecked")
private TypeLiteral getAllBlobsStrategyImplType;
@SuppressWarnings("unchecked")
private TypeLiteral getAllBlobMetadataStrategyType;
@SuppressWarnings("unchecked")
private TypeLiteral getAllBlobMetadataStrategyImplType;
private Builder(TypeLiteral<S> connectionType, TypeLiteral<C> containerMetadataType,
TypeLiteral<M> blobMetadataType, TypeLiteral<B> blobType) {
this.connectionType = connectionType;
this.containerMetadataType = containerMetadataType;
this.blobMetadataType = blobMetadataType;
this.blobType = blobType;
blobMapFactoryType = TypeLiteral.get(Types.newParameterizedTypeWithOwner(BlobMap.class,
BlobMap.Factory.class, blobMetadataType.getType(), blobType.getType()));
blobMapImplType = TypeLiteral.get(Types.newParameterizedType(BlobMapImpl.class,
connectionType.getType(), containerMetadataType.getType(), blobMetadataType
.getType(), blobType.getType()));
inputStreamMapFactoryType = TypeLiteral.get(Types.newParameterizedTypeWithOwner(
InputStreamMap.class, InputStreamMap.Factory.class, blobMetadataType.getType()));
inputStreamMapImplType = TypeLiteral.get(Types.newParameterizedType(
InputStreamMapImpl.class, connectionType.getType(), containerMetadataType
.getType(), blobMetadataType.getType(), blobType.getType()));
getAllBlobsStrategyType = TypeLiteral.get(Types.newParameterizedType(
GetAllBlobsStrategy.class, containerMetadataType.getType(), blobMetadataType
.getType(), blobType.getType()));
setGetAllBlobsStrategyImpl(RetryOnNotFoundGetAllBlobsStrategy.class);
getAllBlobMetadataStrategyType = TypeLiteral.get(Types.newParameterizedType(
GetAllBlobMetadataStrategy.class, containerMetadataType.getType(),
blobMetadataType.getType(), blobType.getType()));
getAllBlobMetadataStrategyImplType = TypeLiteral.get(Types.newParameterizedType(
ContainerListGetAllBlobMetadataStrategy.class, containerMetadataType.getType(),
blobMetadataType.getType(), blobType.getType()));
}
Builder<S, C, M, B> withGetAllBlobsStrategy(Class<?> getAllBlobsStrategyImplClass) {
setGetAllBlobsStrategyImpl(getAllBlobsStrategyImplClass);
return this;
}
private void setGetAllBlobsStrategyImpl(Class<?> getAllBlobsStrategyImplClass) {
getAllBlobsStrategyImplType = TypeLiteral.get(Types.newParameterizedType(
getAllBlobsStrategyImplClass, containerMetadataType.getType(), blobMetadataType
.getType(), blobType.getType()));
}
public static <S extends BlobStore<C, M, B>, C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> Builder<S, C, M, B> newBuilder(
TypeLiteral<S> connectionType, TypeLiteral<C> containerMetadataType,
TypeLiteral<M> blobMetadataType, TypeLiteral<B> blobType) {
return new Builder<S, C, M, B>(connectionType, containerMetadataType, blobMetadataType,
blobType);
}
public BlobStoreMapsModule build() {
return new BlobStoreMapsModule(blobMapFactoryType, blobMapImplType,
inputStreamMapFactoryType, inputStreamMapImplType, getAllBlobsStrategyType,
getAllBlobsStrategyImplType, getAllBlobMetadataStrategyType,
getAllBlobMetadataStrategyImplType);
}
}
@SuppressWarnings("unchecked")
@Override
protected void configure() {
bind(blobMapFactoryType).toProvider(
FactoryProvider.newFactory(blobMapFactoryType, blobMapImplType));
FactoryProvider.newFactory(blobMapFactoryType, blobMapImplType))
.in(Scopes.SINGLETON);
bind(inputStreamMapFactoryType).toProvider(
FactoryProvider.newFactory(inputStreamMapFactoryType, inputStreamMapImplType));
FactoryProvider.newFactory(inputStreamMapFactoryType, inputStreamMapImplType)).in(
Scopes.SINGLETON);
bind(getAllBlobsStrategyType).to(getAllBlobsStrategyImplType).in(Scopes.SINGLETON);
bind(getAllBlobMetadataStrategyType).to(getAllBlobMetadataStrategyImplType).in(
Scopes.SINGLETON);
}
}

View File

@ -21,7 +21,7 @@
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore;
package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@ -29,10 +29,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.SortedSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@ -42,16 +40,17 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.rest.BoundedList;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.rest.BoundedSortedSet;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.assistedinject.Assisted;
@ -68,8 +67,10 @@ import com.google.inject.assistedinject.Assisted;
public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>, V> {
protected final BlobStore<C, M, B> connection;
protected final String container;
protected final String containerName;
protected final Provider<B> blobFactory;
protected final GetAllBlobsStrategy<C, M, B> getAllBlobs;
protected final GetAllBlobMetadataStrategy<C, M, B> getAllBlobMetadata;
/**
* maximum duration of an blob Request
@ -87,32 +88,30 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
@Inject
public BaseBlobMap(BlobStore<C, M, B> connection, Provider<B> blobFactory,
@Assisted String containerName) {
GetAllBlobsStrategy<C, M, B> getAllBlobs,
GetAllBlobMetadataStrategy<C, M, B> getAllBlobMetadata, @Assisted String containerName) {
this.connection = checkNotNull(connection, "connection");
this.container = checkNotNull(containerName, "container");
this.containerName = checkNotNull(containerName, "container");
this.blobFactory = checkNotNull(blobFactory, "blobFactory");
checkArgument(!container.equals(""), "container name must not be a blank string!");
this.getAllBlobs = checkNotNull(getAllBlobs, "getAllBlobs");
this.getAllBlobMetadata = checkNotNull(getAllBlobMetadata, "getAllBlobMetadata");
checkArgument(!containerName.equals(""), "container name must not be a blank string!");
}
/**
* {@inheritDoc}
* <p/>
* This returns the number of keys in the {@link BoundedList}
* This returns the number of keys in the {@link BoundedSortedSet}
*
* @see BoundedList#getContents()
* @see BoundedSortedSet#getContents()
*/
public int size() {
try {
return refreshContainer().size();
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error getting size of container" + container, e);
}
return getAllBlobMetadata.execute(connection, containerName).size();
}
protected boolean containsETag(byte[] eTag) throws InterruptedException, ExecutionException,
TimeoutException {
for (BlobMetadata metadata : refreshContainer()) {
for (BlobMetadata metadata : getAllBlobMetadata.execute(connection, containerName)) {
if (Arrays.equals(eTag, metadata.getETag()))
return true;
}
@ -138,39 +137,10 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
*
* @see BlobStore#getBlob(String, String)
*/
protected Set<B> getAllObjects() {
Set<B> objects = Sets.newHashSet();
Map<String, Future<B>> futureObjects = Maps.newHashMap();
for (String key : keySet()) {
futureObjects.put(key, connection.getBlob(container, key));
}
for (Entry<String, Future<B>> futureObjectEntry : futureObjects.entrySet()) {
try {
ifNotFoundRetryOtherwiseAddToSet(futureObjectEntry.getKey(), futureObjectEntry
.getValue(), objects);
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error getting value from blob %1$s",
container), e);
}
protected Set<B> getAllBlobs() {
}
return objects;
}
return getAllBlobs.execute(connection, containerName);
@VisibleForTesting
public void ifNotFoundRetryOtherwiseAddToSet(String key, Future<B> value, Set<B> objects)
throws InterruptedException, ExecutionException, TimeoutException {
for (int i = 0; i < 3; i++) {
try {
B object = value.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
object.getMetadata().setKey(key);
objects.add(object);
return;
} catch (KeyNotFoundException e) {
Thread.sleep(requestRetryMilliseconds);
}
}
}
/**
@ -190,8 +160,8 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format(
"Error searching for ETAG of value: [%2$s] in container:%1$s", container, value),
e);
"Error searching for ETAG of value: [%2$s] in container:%1$s", containerName,
value), e);
}
}
@ -208,65 +178,48 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
}
public void clear() {
try {
List<Future<Boolean>> deletes = Lists.newArrayList();
for (String key : keySet()) {
deletes.add(connection.removeBlob(container, key));
}
for (Future<Boolean> isdeleted : deletes)
if (!isdeleted.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) {
throw new BlobRuntimeException("failed to delete entry");
}
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error clearing container" + container, e);
Set<Future<Boolean>> deletes = Sets.newHashSet();
for (M md : getAllBlobMetadata.execute(connection, containerName)) {
deletes.add(connection.removeBlob(containerName, md.getKey()));
}
for (Future<Boolean> isdeleted : deletes) {
try {
if (!isdeleted.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) {
throw new BlobRuntimeException("Failed to delete blob in container: "
+ containerName);
}
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error deleting blob in container: " + containerName, e);
}
}
}
/**
*
* @throws ContainerNotFoundException
* when the container doesn't exist
*/
protected List<M> refreshContainer() throws InterruptedException, ExecutionException,
TimeoutException {
return connection.listBlobs(container).get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
}
public Set<String> keySet() {
try {
Set<String> keys = Sets.newHashSet();
for (BlobMetadata object : refreshContainer())
keys.add(object.getKey());
return keys;
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error getting keys in container: " + container, e);
}
Set<String> keys = Sets.newHashSet();
for (BlobMetadata object : getAllBlobMetadata.execute(connection, containerName))
keys.add(object.getKey());
return keys;
}
public boolean containsKey(Object key) {
try {
return connection.blobMetadata(container, key.toString()) != null;
return connection.blobMetadata(containerName, key.toString()) != null;
} catch (KeyNotFoundException e) {
return false;
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error searching for %1$s:%2$s", container,
key), e);
throw new BlobRuntimeException(String.format("Error searching for %1$s:%2$s",
containerName, key), e);
}
}
public boolean isEmpty() {
return keySet().size() == 0;
return size() == 0;
}
public List<M> listContainer() {
try {
return refreshContainer();
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error getting container" + container, e);
}
public SortedSet<M> listContainer() {
return getAllBlobMetadata.execute(connection, containerName);
}
}

View File

@ -23,10 +23,8 @@
*/
package org.jclouds.blobstore.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
@ -35,15 +33,17 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.blobstore.BaseBlobMap;
import org.jclouds.blobstore.BlobMap;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.util.Utils;
import com.google.common.collect.Sets;
import com.google.inject.assistedinject.Assisted;
/**
@ -59,8 +59,9 @@ public class BlobMapImpl<S extends BlobStore<C, M, B>, C extends ContainerMetada
@Inject
public BlobMapImpl(S connection, Provider<B> blobFactory,
@Assisted String containerName) {
super(connection, blobFactory, containerName);
GetAllBlobsStrategy<C, M, B> getAllBlobs,
GetAllBlobMetadataStrategy<C, M, B> getAllBlobMetadata, @Assisted String containerName) {
super(connection, blobFactory, getAllBlobs, getAllBlobMetadata, containerName);
}
/**
@ -113,14 +114,14 @@ public class BlobMapImpl<S extends BlobStore<C, M, B>, C extends ContainerMetada
*/
public B get(Object key) {
try {
return connection.getBlob(container, key.toString()).get(requestTimeoutMilliseconds,
return connection.getBlob(containerName, key.toString()).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
} catch (KeyNotFoundException e) {
return null;
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error geting object %1$s:%2$s", container,
key), e);
throw new BlobRuntimeException(String.format("Error geting object %1$s:%2$s",
containerName, key), e);
}
}
@ -132,12 +133,12 @@ public class BlobMapImpl<S extends BlobStore<C, M, B>, C extends ContainerMetada
public B put(String key, B value) {
B returnVal = getLastValue(key);
try {
connection.putBlob(container, value)
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
connection.putBlob(containerName, value).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error putting object %1$s:%2$s%n%3$s",
container, key, value), e);
containerName, key, value), e);
}
return returnVal;
}
@ -149,16 +150,16 @@ public class BlobMapImpl<S extends BlobStore<C, M, B>, C extends ContainerMetada
*/
public void putAll(Map<? extends String, ? extends B> map) {
try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
Set<Future<byte[]>> puts = Sets.newHashSet();
for (B object : map.values()) {
puts.add(connection.putBlob(container, object));
puts.add(connection.putBlob(containerName, object));
}
for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error putting into containerName" + container, e);
throw new BlobRuntimeException("Error putting into containerName" + containerName, e);
}
}
@ -170,12 +171,12 @@ public class BlobMapImpl<S extends BlobStore<C, M, B>, C extends ContainerMetada
public B remove(Object key) {
B old = getLastValue(key);
try {
connection.removeBlob(container, key.toString()).get(requestTimeoutMilliseconds,
connection.removeBlob(containerName, key.toString()).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error removing object %1$s:%2$s", container,
key), e);
throw new BlobRuntimeException(String.format("Error removing object %1$s:%2$s",
containerName, key), e);
}
return old;
}
@ -196,7 +197,6 @@ public class BlobMapImpl<S extends BlobStore<C, M, B>, C extends ContainerMetada
* @see #getAllObjects()
*/
public Collection<B> values() {
return getAllObjects();
return super.getAllBlobs();
}
}

View File

@ -25,11 +25,9 @@ package org.jclouds.blobstore.internal;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
@ -38,16 +36,18 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Provider;
import org.jclouds.blobstore.BaseBlobMap;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.InputStreamMap;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import com.google.inject.assistedinject.Assisted;
/**
@ -64,8 +64,9 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
@Inject
public InputStreamMapImpl(S connection, Provider<B> blobFactory,
@Assisted String container) {
super(connection, blobFactory, container);
GetAllBlobsStrategy<C, M, B> getAllBlobs,
GetAllBlobMetadataStrategy<C, M, B> getAllBlobMetadata, @Assisted String containerName) {
super(connection, blobFactory, getAllBlobs, getAllBlobMetadata, containerName);
}
/**
@ -75,14 +76,14 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
*/
public InputStream get(Object o) {
try {
return (InputStream) (connection.getBlob(container, o.toString()).get(
return (InputStream) (connection.getBlob(containerName, o.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).getData();
} catch (KeyNotFoundException e) {
return null;
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String
.format("Error geting object %1$s:%2$s", container, o), e);
throw new BlobRuntimeException(String.format("Error geting object %1$s:%2$s",
containerName, o), e);
}
}
@ -94,12 +95,12 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
public InputStream remove(Object o) {
InputStream old = getLastValue(o);
try {
connection.removeBlob(container, o.toString()).get(requestTimeoutMilliseconds,
connection.removeBlob(containerName, o.toString()).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error removing object %1$s:%2$s", container,
o), e);
throw new BlobRuntimeException(String.format("Error removing object %1$s:%2$s",
containerName, o), e);
}
return old;
}
@ -121,7 +122,7 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
*/
public Collection<InputStream> values() {
Collection<InputStream> values = new LinkedList<InputStream>();
Set<B> objects = getAllObjects();
Set<B> objects = this.getAllBlobs.execute(connection, containerName);
for (B object : objects) {
values.add((InputStream) object.getData());
}
@ -135,7 +136,7 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
*/
public Set<Map.Entry<String, InputStream>> entrySet() {
Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>();
for (B object : getAllObjects()) {
for (B object : this.getAllBlobs.execute(connection, containerName)) {
entrySet.add(new Entry(object.getKey(), (InputStream) object.getData()));
}
return entrySet;
@ -215,13 +216,13 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
@VisibleForTesting
void putAllInternal(Map<? extends String, ? extends Object> map) {
try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>();
Set<Future<byte[]>> puts = Sets.newHashSet();
for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
B object = blobFactory.get();
object.getMetadata().setKey(entry.getKey());
object.setData(entry.getValue());
object.generateMD5();
puts.add(connection.putBlob(container, object));
puts.add(connection.putBlob(containerName, object));
// / ParamExtractor Funcion<?,String>
// / response transformer set key on the way out.
// / ExceptionHandler convert 404 to NOT_FOUND
@ -231,7 +232,7 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error putting into containerName" + container, e);
throw new BlobRuntimeException("Error putting into containerName" + containerName, e);
}
}
@ -285,13 +286,13 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
InputStream returnVal = containsKey(s) ? get(s) : null;
object.setData(o);
object.generateMD5();
connection.putBlob(container, object).get(requestTimeoutMilliseconds,
connection.putBlob(containerName, object).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
return returnVal;
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error adding object %1$s:%2$s", container,
object), e);
throw new BlobRuntimeException(String.format("Error adding object %1$s:%2$s",
containerName, object), e);
}
}

View File

@ -0,0 +1,42 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.strategy;
import java.util.SortedSet;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
/**
* Retrieves all blobs in the blobstore by the most efficient means possible.
*
* @author Adrian Cole
*/
public interface GetAllBlobMetadataStrategy<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> {
SortedSet<M> execute(BlobStore<C, M, B> connection, String containerName);
}

View File

@ -0,0 +1,42 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.strategy;
import java.util.SortedSet;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
/**
* Retrieves all blobs in the blobstore by the most efficient means possible.
*
* @author Adrian Cole
*/
public interface GetAllBlobsStrategy<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> {
SortedSet<B> execute(BlobStore<C, M, B> connection, String containerName);
}

View File

@ -0,0 +1,64 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.strategy.internal;
import java.util.SortedSet;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.internal.BaseBlobMap.BlobRuntimeException;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.util.Utils;
/**
* Retrieves all blobs in the blobstore by the most efficient means possible.
*
* @author Adrian Cole
*/
public class ContainerListGetAllBlobMetadataStrategy<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>>
implements GetAllBlobMetadataStrategy<C, M, B> {
/**
* maximum duration of an blob Request
*/
@Inject(optional = true)
@Named(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT)
protected long requestTimeoutMilliseconds = 30000;
public SortedSet<M> execute(BlobStore<C, M, B> connection, String container) {
try {
return connection.listBlobs(container).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS);
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error getting blob metadata in container: " + container, e);
}
}
}

View File

@ -0,0 +1,115 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.strategy.internal;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.internal.BaseBlobMap.BlobRuntimeException;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* Retrieves all blobs in the blobstore by the most efficient means possible.
*
* @author Adrian Cole
*/
public class RetryOnNotFoundGetAllBlobsStrategy<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>>
implements GetAllBlobsStrategy<C, M, B> {
/**
* maximum duration of an blob Request
*/
@Inject(optional = true)
@Named(BlobStoreConstants.PROPERTY_BLOBSTORE_TIMEOUT)
public long requestTimeoutMilliseconds = 30000;
protected final GetAllBlobMetadataStrategy<C, M, B> getAllBlobMetadata;
/**
* time to pause before retrying a transient failure
*/
@Inject(optional = true)
@Named(BlobStoreConstants.PROPERTY_BLOBSTORE_RETRY)
protected long requestRetryMilliseconds = 10;
@Inject
RetryOnNotFoundGetAllBlobsStrategy(GetAllBlobMetadataStrategy<C, M, B> getAllBlobMetadata) {
this.getAllBlobMetadata = getAllBlobMetadata;
}
public SortedSet<B> execute(BlobStore<C, M, B> connection, String container) {
SortedSet<B> objects = Sets.<B> newTreeSet();
Map<String, Future<B>> futureObjects = Maps.newHashMap();
for (M md : getAllBlobMetadata.execute(connection, container)) {
futureObjects.put(md.getKey(), connection.getBlob(container, md.getKey()));
}
for (Entry<String, Future<B>> futureObjectEntry : futureObjects.entrySet()) {
try {
ifNotFoundRetryOtherwiseAddToSet(futureObjectEntry.getKey(), futureObjectEntry
.getValue(), objects);
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error getting value from blob %1$s",
container), e);
}
}
return objects;
}
@VisibleForTesting
public void ifNotFoundRetryOtherwiseAddToSet(String key, Future<B> value, Set<B> objects)
throws InterruptedException, ExecutionException, TimeoutException {
for (int i = 0; i < 3; i++) {
try {
B object = value.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
object.getMetadata().setKey(key);
objects.add(object);
return;
} catch (KeyNotFoundException e) {
Thread.sleep(requestRetryMilliseconds);
}
}
}
}

View File

@ -0,0 +1,118 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.config.StubBlobStoreConnectionModule;
import org.jclouds.blobstore.internal.BlobMapImpl;
import org.jclouds.blobstore.internal.InputStreamMapImpl;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.blobstore.strategy.internal.ContainerListGetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.internal.RetryOnNotFoundGetAllBlobsStrategy;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
@Test(groups = "unit", testName = "blobstore.BlobStoreMapsModuleTest")
public class BlobStoreMapsModuleTest {
public void testBuilderBuild() {
BlobStoreMapsModule module = BlobStoreMapsModule.Builder.newBuilder(
new TypeLiteral<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
}, new TypeLiteral<ContainerMetadata>() {
}, new TypeLiteral<BlobMetadata>() {
}, new TypeLiteral<Blob<BlobMetadata>>() {
}).build();
assertEquals(module.blobMapFactoryType,
new TypeLiteral<BlobMap.Factory<BlobMetadata, Blob<BlobMetadata>>>() {
});
assertEquals(
module.blobMapImplType,
new TypeLiteral<BlobMapImpl<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
});
assertEquals(module.inputStreamMapFactoryType,
new TypeLiteral<InputStreamMap.Factory<BlobMetadata>>() {
});
assertEquals(
module.inputStreamMapImplType,
new TypeLiteral<InputStreamMapImpl<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>, ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
});
assertEquals(
module.getAllBlobsStrategyType,
new TypeLiteral<GetAllBlobsStrategy<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
});
assertEquals(
module.getAllBlobsStrategyImplType,
new TypeLiteral<RetryOnNotFoundGetAllBlobsStrategy<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
});
assertEquals(
module.getAllBlobMetadataStrategyType,
new TypeLiteral<GetAllBlobMetadataStrategy<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
});
assertEquals(
module.getAllBlobMetadataStrategyImplType,
new TypeLiteral<ContainerListGetAllBlobMetadataStrategy<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
});
}
public void testInject() {
Injector i = Guice
.createInjector(
new StubBlobStoreConnectionModule(),
BlobStoreMapsModule.Builder
.newBuilder(
new TypeLiteral<BlobStore<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
}, new TypeLiteral<ContainerMetadata>() {
}, new TypeLiteral<BlobMetadata>() {
}, new TypeLiteral<Blob<BlobMetadata>>() {
}).build());
assertNotNull(i.getInstance(Key
.get(new TypeLiteral<BlobMap.Factory<BlobMetadata, Blob<BlobMetadata>>>() {
})));
assertNotNull(i.getInstance(Key.get(new TypeLiteral<InputStreamMap.Factory<BlobMetadata>>() {
})));
assertEquals(
i
.getInstance(
Key
.get(new TypeLiteral<GetAllBlobsStrategy<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
})).getClass(), RetryOnNotFoundGetAllBlobsStrategy.class);
assertEquals(
i
.getInstance(
Key
.get(new TypeLiteral<GetAllBlobMetadataStrategy<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
})).getClass(),
ContainerListGetAllBlobMetadataStrategy.class);
}
}

View File

@ -28,9 +28,9 @@ import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException;
@ -56,10 +56,10 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeSuite;
import org.testng.collections.Lists;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.inject.Module;
public class BaseBlobStoreIntegrationTest<S extends BlobStore<C, M, B>, C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> {
@ -171,7 +171,7 @@ public class BaseBlobStoreIntegrationTest<S extends BlobStore<C, M, B>, C extend
}
}
private static final List<String> blackListContainers = Lists.newArrayList();
private static final Set<String> blackListContainers = Sets.newHashSet();
/**
* Tries to delete all containers, runs up to two times
@ -182,7 +182,7 @@ public class BaseBlobStoreIntegrationTest<S extends BlobStore<C, M, B>, C extend
try {
for (int i = 0; i < 2; i++) {
Iterable<ContainerMetadata> testContainers = Iterables.filter(
(List<ContainerMetadata>) context.getApi().listContainers(),
(SortedSet<ContainerMetadata>) context.getApi().listContainers(),
new Predicate<ContainerMetadata>() {
public boolean apply(ContainerMetadata input) {
return input.getName().startsWith(CONTAINER_PREFIX.toLowerCase());

View File

@ -21,27 +21,20 @@
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore;
package org.jclouds.blobstore.internal;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.blobstore.BlobMap;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.BlobStoreContextImpl;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder;
import org.jclouds.blobstore.internal.InputStreamMapImpl;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@ -105,41 +98,4 @@ public class BaseBlobMapTest {
}
@SuppressWarnings("unchecked")
public void testIfNotFoundRetryOtherwiseAddToSet() throws InterruptedException,
ExecutionException, TimeoutException {
Future<Blob<BlobMetadata>> futureObject = createMock(Future.class);
Blob<BlobMetadata> object = context.newBlob("key");
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow(
new KeyNotFoundException());
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andReturn(
object);
replay(futureObject);
Set<Blob<BlobMetadata>> objects = new HashSet<Blob<BlobMetadata>>();
long time = System.currentTimeMillis();
map.ifNotFoundRetryOtherwiseAddToSet("key", futureObject, objects);
// should have retried once
assert System.currentTimeMillis() >= time + map.requestRetryMilliseconds;
assert objects.contains(object);
assert !objects.contains(null);
}
@SuppressWarnings("unchecked")
public void testIfNotFoundRetryOtherwiseAddToSetButNeverGetsIt() throws InterruptedException,
ExecutionException, TimeoutException {
Future<Blob<BlobMetadata>> futureObject = createMock(Future.class);
Blob object = createNiceMock(Blob.class);
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow(
new KeyNotFoundException()).atLeastOnce();
replay(futureObject);
Set<Blob<BlobMetadata>> objects = new HashSet<Blob<BlobMetadata>>();
long time = System.currentTimeMillis();
map.ifNotFoundRetryOtherwiseAddToSet("key", futureObject, objects);
// should have retried thrice
assert System.currentTimeMillis() >= time + map.requestRetryMilliseconds * 3;
assert !objects.contains(object);
assert !objects.contains(null);
}
}

View File

@ -0,0 +1,109 @@
/**
*
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.blobstore.strategy.internal;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
/**
*
* Tests retry logic.
*
* @author Adrian Cole
*/
@Test(groups = { "unit" }, testName = "blobstore.RetryOnNotFoundGetAllBlobsStrategyTest")
public class RetryOnNotFoundGetAllBlobsStrategyTest {
Injector context;
RetryOnNotFoundGetAllBlobsStrategy<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>> map;
@BeforeClass
void addDefaultObjectsSoThatTestsWillPass() {
context = new StubBlobStoreContextBuilder().buildInjector();
map = context
.getInstance(Key
.get(new TypeLiteral<RetryOnNotFoundGetAllBlobsStrategy<ContainerMetadata, BlobMetadata, Blob<BlobMetadata>>>() {
}));
}
@SuppressWarnings("unchecked")
public void testIfNotFoundRetryOtherwiseAddToSet() throws InterruptedException,
ExecutionException, TimeoutException {
Future<Blob<BlobMetadata>> futureObject = createMock(Future.class);
Blob<BlobMetadata> object = new Blob<BlobMetadata>("key");
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow(
new KeyNotFoundException());
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andReturn(
object);
replay(futureObject);
Set<Blob<BlobMetadata>> objects = new HashSet<Blob<BlobMetadata>>();
long time = System.currentTimeMillis();
map.ifNotFoundRetryOtherwiseAddToSet("key", futureObject, objects);
// should have retried once
assert System.currentTimeMillis() >= time + map.requestRetryMilliseconds;
assert objects.contains(object);
assert !objects.contains(null);
}
@SuppressWarnings("unchecked")
public void testIfNotFoundRetryOtherwiseAddToSetButNeverGetsIt() throws InterruptedException,
ExecutionException, TimeoutException {
Future<Blob<BlobMetadata>> futureObject = createMock(Future.class);
Blob object = createNiceMock(Blob.class);
expect(futureObject.get(map.requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).andThrow(
new KeyNotFoundException()).atLeastOnce();
replay(futureObject);
Set<Blob<BlobMetadata>> objects = new HashSet<Blob<BlobMetadata>>();
long time = System.currentTimeMillis();
map.ifNotFoundRetryOtherwiseAddToSet("key", futureObject, objects);
// should have retried thrice
assert System.currentTimeMillis() >= time + map.requestRetryMilliseconds * 3;
assert !objects.contains(object);
assert !objects.contains(null);
}
}