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.containerMetadataType = containerMetadataType;
this.blobMetadataType = blobMetadataType; this.blobMetadataType = blobMetadataType;
this.blobType = blobType; this.blobType = blobType;
modules.add(new BlobStoreMapsModule<S, C, M, B>(connectionType, modules.add(BlobStoreMapsModule.Builder.newBuilder(connectionType,
containerMetadataType, blobMetadataType, blobType)); containerMetadataType, blobMetadataType, blobType).build());
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -23,15 +23,18 @@
*/ */
package org.jclouds.blobstore; package org.jclouds.blobstore;
import javax.inject.Inject;
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.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.internal.BlobMapImpl; import org.jclouds.blobstore.internal.BlobMapImpl;
import org.jclouds.blobstore.internal.InputStreamMapImpl; 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.AbstractModule;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryProvider; import com.google.inject.assistedinject.FactoryProvider;
import com.google.inject.util.Types; import com.google.inject.util.Types;
@ -39,42 +42,134 @@ import com.google.inject.util.Types;
/** /**
* @author Adrian Cole * @author Adrian Cole
*/ */
public class BlobStoreMapsModule<S extends BlobStore<C, M, B>, C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> public class BlobStoreMapsModule extends AbstractModule {
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 // 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. // generic types into provider methods. This is why we are sending in TypeLiterals.
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private final TypeLiteral blobMapFactoryType; protected final TypeLiteral blobMapFactoryType;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private final TypeLiteral blobMapImplType; protected final TypeLiteral blobMapImplType;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private final TypeLiteral inputStreamMapFactoryType; protected final TypeLiteral inputStreamMapFactoryType;
@SuppressWarnings("unchecked") @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 static class Builder<S extends BlobStore<C, M, B>, C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> {
public BlobStoreMapsModule(TypeLiteral<S> connectionType, TypeLiteral<C> containerMetadataType, @SuppressWarnings("unused")
TypeLiteral<M> blobMetadataType, TypeLiteral<B> blobType) { private final TypeLiteral<S> connectionType;
blobMapFactoryType = TypeLiteral.get(Types.newParameterizedTypeWithOwner(BlobMap.class, private final TypeLiteral<C> containerMetadataType;
BlobMap.Factory.class, blobMetadataType.getType(), blobType.getType())); private final TypeLiteral<M> blobMetadataType;
blobMapImplType = TypeLiteral.get(Types.newParameterizedType(BlobMapImpl.class, private final TypeLiteral<B> blobType;
connectionType.getType(), containerMetadataType.getType(), blobMetadataType @SuppressWarnings("unchecked")
.getType(), blobType.getType())); private TypeLiteral blobMapFactoryType;
inputStreamMapFactoryType = TypeLiteral.get(Types.newParameterizedTypeWithOwner( @SuppressWarnings("unchecked")
InputStreamMap.class, InputStreamMap.Factory.class, blobMetadataType.getType())); private TypeLiteral blobMapImplType;
inputStreamMapImplType = TypeLiteral.get(Types.newParameterizedType(InputStreamMapImpl.class, @SuppressWarnings("unchecked")
connectionType.getType(), containerMetadataType.getType(), blobMetadataType private TypeLiteral inputStreamMapFactoryType;
.getType(), blobType.getType())); @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") @SuppressWarnings("unchecked")
@Override @Override
protected void configure() { protected void configure() {
bind(blobMapFactoryType).toProvider( bind(blobMapFactoryType).toProvider(
FactoryProvider.newFactory(blobMapFactoryType, blobMapImplType)); FactoryProvider.newFactory(blobMapFactoryType, blobMapImplType))
.in(Scopes.SINGLETON);
bind(inputStreamMapFactoryType).toProvider( 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. * 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.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; 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.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Map.Entry; import java.util.SortedSet;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -42,16 +40,17 @@ import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider; 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.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.reference.BlobStoreConstants; 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 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.common.collect.Sets;
import com.google.inject.assistedinject.Assisted; 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> { public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>, V> {
protected final BlobStore<C, M, B> connection; protected final BlobStore<C, M, B> connection;
protected final String container; protected final String containerName;
protected final Provider<B> blobFactory; 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 * maximum duration of an blob Request
@ -87,32 +88,30 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
@Inject @Inject
public BaseBlobMap(BlobStore<C, M, B> connection, Provider<B> blobFactory, 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.connection = checkNotNull(connection, "connection");
this.container = checkNotNull(containerName, "container"); this.containerName = checkNotNull(containerName, "container");
this.blobFactory = checkNotNull(blobFactory, "blobFactory"); 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} * {@inheritDoc}
* <p/> * <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() { public int size() {
try { return getAllBlobMetadata.execute(connection, containerName).size();
return refreshContainer().size();
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error getting size of container" + container, e);
}
} }
protected boolean containsETag(byte[] eTag) throws InterruptedException, ExecutionException, protected boolean containsETag(byte[] eTag) throws InterruptedException, ExecutionException,
TimeoutException { TimeoutException {
for (BlobMetadata metadata : refreshContainer()) { for (BlobMetadata metadata : getAllBlobMetadata.execute(connection, containerName)) {
if (Arrays.equals(eTag, metadata.getETag())) if (Arrays.equals(eTag, metadata.getETag()))
return true; return true;
} }
@ -138,39 +137,10 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
* *
* @see BlobStore#getBlob(String, String) * @see BlobStore#getBlob(String, String)
*/ */
protected Set<B> getAllObjects() { protected Set<B> getAllBlobs() {
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);
}
} return getAllBlobs.execute(connection, containerName);
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);
}
}
} }
/** /**
@ -190,8 +160,8 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format( throw new BlobRuntimeException(String.format(
"Error searching for ETAG of value: [%2$s] in container:%1$s", container, value), "Error searching for ETAG of value: [%2$s] in container:%1$s", containerName,
e); value), e);
} }
} }
@ -208,65 +178,48 @@ public abstract class BaseBlobMap<C extends ContainerMetadata, M extends BlobMet
} }
public void clear() { public void clear() {
try { Set<Future<Boolean>> deletes = Sets.newHashSet();
List<Future<Boolean>> deletes = Lists.newArrayList(); for (M md : getAllBlobMetadata.execute(connection, containerName)) {
for (String key : keySet()) { deletes.add(connection.removeBlob(containerName, md.getKey()));
deletes.add(connection.removeBlob(container, key)); }
} for (Future<Boolean> isdeleted : deletes) {
for (Future<Boolean> isdeleted : deletes) try {
if (!isdeleted.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) { if (!isdeleted.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)) {
throw new BlobRuntimeException("failed to delete entry"); throw new BlobRuntimeException("Failed to delete blob in container: "
} + containerName);
} catch (Exception e) { }
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); } catch (Exception e) {
throw new BlobRuntimeException("Error clearing container" + container, 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() { public Set<String> keySet() {
try { Set<String> keys = Sets.newHashSet();
Set<String> keys = Sets.newHashSet(); for (BlobMetadata object : getAllBlobMetadata.execute(connection, containerName))
for (BlobMetadata object : refreshContainer()) keys.add(object.getKey());
keys.add(object.getKey()); return keys;
return keys;
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error getting keys in container: " + container, e);
}
} }
public boolean containsKey(Object key) { public boolean containsKey(Object key) {
try { try {
return connection.blobMetadata(container, key.toString()) != null; return connection.blobMetadata(containerName, key.toString()) != null;
} catch (KeyNotFoundException e) { } catch (KeyNotFoundException e) {
return false; return false;
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error searching for %1$s:%2$s", container, throw new BlobRuntimeException(String.format("Error searching for %1$s:%2$s",
key), e); containerName, key), e);
} }
} }
public boolean isEmpty() { public boolean isEmpty() {
return keySet().size() == 0; return size() == 0;
}
public SortedSet<M> listContainer() {
return getAllBlobMetadata.execute(connection, containerName);
} }
public List<M> listContainer() {
try {
return refreshContainer();
} catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException("Error getting container" + container, e);
}
}
} }

View File

@ -23,10 +23,8 @@
*/ */
package org.jclouds.blobstore.internal; package org.jclouds.blobstore.internal;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -35,15 +33,17 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider; import javax.inject.Provider;
import org.jclouds.blobstore.BaseBlobMap;
import org.jclouds.blobstore.BlobMap; import org.jclouds.blobstore.BlobMap;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.KeyNotFoundException;
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.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.collect.Sets;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
/** /**
@ -59,8 +59,9 @@ public class BlobMapImpl<S extends BlobStore<C, M, B>, C extends ContainerMetada
@Inject @Inject
public BlobMapImpl(S connection, Provider<B> blobFactory, public BlobMapImpl(S connection, Provider<B> blobFactory,
@Assisted String containerName) { GetAllBlobsStrategy<C, M, B> getAllBlobs,
super(connection, blobFactory, containerName); 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) { public B get(Object key) {
try { try {
return connection.getBlob(container, key.toString()).get(requestTimeoutMilliseconds, return connection.getBlob(containerName, key.toString()).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} catch (KeyNotFoundException e) { } catch (KeyNotFoundException e) {
return null; return null;
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error geting object %1$s:%2$s", container, throw new BlobRuntimeException(String.format("Error geting object %1$s:%2$s",
key), e); 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) { public B put(String key, B value) {
B returnVal = getLastValue(key); B returnVal = getLastValue(key);
try { try {
connection.putBlob(container, value) connection.putBlob(containerName, value).get(requestTimeoutMilliseconds,
.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error putting object %1$s:%2$s%n%3$s", 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; 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) { public void putAll(Map<? extends String, ? extends B> map) {
try { try {
List<Future<byte[]>> puts = new ArrayList<Future<byte[]>>(); Set<Future<byte[]>> puts = Sets.newHashSet();
for (B object : map.values()) { for (B object : map.values()) {
puts.add(connection.putBlob(container, object)); puts.add(connection.putBlob(containerName, object));
} }
for (Future<byte[]> put : puts) for (Future<byte[]> put : puts)
// this will throw an exception if there was a problem // this will throw an exception if there was a problem
put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS); put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(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) { public B remove(Object key) {
B old = getLastValue(key); B old = getLastValue(key);
try { try {
connection.removeBlob(container, key.toString()).get(requestTimeoutMilliseconds, connection.removeBlob(containerName, key.toString()).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error removing object %1$s:%2$s", container, throw new BlobRuntimeException(String.format("Error removing object %1$s:%2$s",
key), e); containerName, key), e);
} }
return old; return old;
} }
@ -196,7 +197,6 @@ public class BlobMapImpl<S extends BlobStore<C, M, B>, C extends ContainerMetada
* @see #getAllObjects() * @see #getAllObjects()
*/ */
public Collection<B> values() { 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.File;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -38,16 +36,18 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider; import javax.inject.Provider;
import org.jclouds.blobstore.BaseBlobMap;
import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.InputStreamMap; import org.jclouds.blobstore.InputStreamMap;
import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.KeyNotFoundException;
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.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.strategy.GetAllBlobMetadataStrategy;
import org.jclouds.blobstore.strategy.GetAllBlobsStrategy;
import org.jclouds.util.Utils; import org.jclouds.util.Utils;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
/** /**
@ -64,8 +64,9 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
@Inject @Inject
public InputStreamMapImpl(S connection, Provider<B> blobFactory, public InputStreamMapImpl(S connection, Provider<B> blobFactory,
@Assisted String container) { GetAllBlobsStrategy<C, M, B> getAllBlobs,
super(connection, blobFactory, container); 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) { public InputStream get(Object o) {
try { try {
return (InputStream) (connection.getBlob(container, o.toString()).get( return (InputStream) (connection.getBlob(containerName, o.toString()).get(
requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).getData(); requestTimeoutMilliseconds, TimeUnit.MILLISECONDS)).getData();
} catch (KeyNotFoundException e) { } catch (KeyNotFoundException e) {
return null; return null;
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String throw new BlobRuntimeException(String.format("Error geting object %1$s:%2$s",
.format("Error geting object %1$s:%2$s", container, o), e); containerName, o), e);
} }
} }
@ -94,12 +95,12 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
public InputStream remove(Object o) { public InputStream remove(Object o) {
InputStream old = getLastValue(o); InputStream old = getLastValue(o);
try { try {
connection.removeBlob(container, o.toString()).get(requestTimeoutMilliseconds, connection.removeBlob(containerName, o.toString()).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error removing object %1$s:%2$s", container, throw new BlobRuntimeException(String.format("Error removing object %1$s:%2$s",
o), e); containerName, o), e);
} }
return old; return old;
} }
@ -121,7 +122,7 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
*/ */
public Collection<InputStream> values() { public Collection<InputStream> values() {
Collection<InputStream> values = new LinkedList<InputStream>(); Collection<InputStream> values = new LinkedList<InputStream>();
Set<B> objects = getAllObjects(); Set<B> objects = this.getAllBlobs.execute(connection, containerName);
for (B object : objects) { for (B object : objects) {
values.add((InputStream) object.getData()); 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() { public Set<Map.Entry<String, InputStream>> entrySet() {
Set<Map.Entry<String, InputStream>> entrySet = new HashSet<Map.Entry<String, InputStream>>(); 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())); entrySet.add(new Entry(object.getKey(), (InputStream) object.getData()));
} }
return entrySet; return entrySet;
@ -215,13 +216,13 @@ public class InputStreamMapImpl<S extends BlobStore<C, M, B>, C extends Containe
@VisibleForTesting @VisibleForTesting
void putAllInternal(Map<? extends String, ? extends Object> map) { void putAllInternal(Map<? extends String, ? extends Object> map) {
try { 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()) { for (Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
B object = blobFactory.get(); B object = blobFactory.get();
object.getMetadata().setKey(entry.getKey()); object.getMetadata().setKey(entry.getKey());
object.setData(entry.getValue()); object.setData(entry.getValue());
object.generateMD5(); object.generateMD5();
puts.add(connection.putBlob(container, object)); puts.add(connection.putBlob(containerName, object));
// / ParamExtractor Funcion<?,String> // / ParamExtractor Funcion<?,String>
// / response transformer set key on the way out. // / response transformer set key on the way out.
// / ExceptionHandler convert 404 to NOT_FOUND // / 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); put.get(requestTimeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(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; InputStream returnVal = containsKey(s) ? get(s) : null;
object.setData(o); object.setData(o);
object.generateMD5(); object.generateMD5();
connection.putBlob(container, object).get(requestTimeoutMilliseconds, connection.putBlob(containerName, object).get(requestTimeoutMilliseconds,
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
return returnVal; return returnVal;
} catch (Exception e) { } catch (Exception e) {
Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e); Utils.<BlobRuntimeException> rethrowIfRuntimeOrSameType(e);
throw new BlobRuntimeException(String.format("Error adding object %1$s:%2$s", container, throw new BlobRuntimeException(String.format("Error adding object %1$s:%2$s",
object), e); 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.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
@ -56,10 +56,10 @@ import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeSuite; import org.testng.annotations.BeforeSuite;
import org.testng.collections.Lists;
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.Sets;
import com.google.inject.Module; import com.google.inject.Module;
public class BaseBlobStoreIntegrationTest<S extends BlobStore<C, M, B>, C extends ContainerMetadata, M extends BlobMetadata, B extends Blob<M>> { 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 * 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 { try {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
Iterable<ContainerMetadata> testContainers = Iterables.filter( Iterable<ContainerMetadata> testContainers = Iterables.filter(
(List<ContainerMetadata>) context.getApi().listContainers(), (SortedSet<ContainerMetadata>) context.getApi().listContainers(),
new Predicate<ContainerMetadata>() { new Predicate<ContainerMetadata>() {
public boolean apply(ContainerMetadata input) { public boolean apply(ContainerMetadata input) {
return input.getName().startsWith(CONTAINER_PREFIX.toLowerCase()); return input.getName().startsWith(CONTAINER_PREFIX.toLowerCase());

View File

@ -21,27 +21,20 @@
* under the License. * 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 static org.testng.Assert.assertEquals;
import java.util.HashSet;
import java.util.Map; 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.Blob;
import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.ContainerMetadata; import org.jclouds.blobstore.domain.ContainerMetadata;
import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder; import org.jclouds.blobstore.integration.StubBlobStoreContextBuilder;
import org.jclouds.blobstore.internal.InputStreamMapImpl;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; 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);
}
}