mirror of https://github.com/apache/jclouds.git
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:
parent
f78670f871
commit
16de6c839c
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue