mirror of https://github.com/apache/jclouds.git
Introduce TransientStorageStrategy
This allows code from the filesystem blobstore to be more similar to the transient blobstore. This commit also corrects a bug where blobExists did not throw an exception when the container did not exist.
This commit is contained in:
parent
3a0c15b345
commit
442c51eb3c
|
@ -148,7 +148,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container, ListContainerOptions options) {
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container, ListContainerOptions options) {
|
||||||
|
|
||||||
// Check if the container exists
|
// Check if the container exists
|
||||||
if (!containerExistsSyncImpl(container))
|
if (!storageStrategy.containerExists(container))
|
||||||
return immediateFailedFuture(cnfe(container));
|
return immediateFailedFuture(cnfe(container));
|
||||||
|
|
||||||
// Loading blobs from container
|
// Loading blobs from container
|
||||||
|
@ -242,7 +242,9 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContainerNotFoundException cnfe(final String name) {
|
private ContainerNotFoundException cnfe(final String name) {
|
||||||
return new ContainerNotFoundException(name, String.format("container %s not in filesystem", name));
|
return new ContainerNotFoundException(name, String.format(
|
||||||
|
"container %s not in %s", name,
|
||||||
|
storageStrategy.getAllContainerNames()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
|
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
|
||||||
|
@ -304,7 +306,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> containerExists(final String containerName) {
|
public ListenableFuture<Boolean> containerExists(final String containerName) {
|
||||||
return immediateFuture(containerExistsSyncImpl(containerName));
|
return immediateFuture(storageStrategy.containerExists(containerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -503,6 +505,8 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> blobExists(final String containerName, final String key) {
|
public ListenableFuture<Boolean> blobExists(final String containerName, final String key) {
|
||||||
|
if (!storageStrategy.containerExists(containerName))
|
||||||
|
return immediateFailedFuture(cnfe(containerName));
|
||||||
return immediateFuture(storageStrategy.blobExists(containerName, key));
|
return immediateFuture(storageStrategy.blobExists(containerName, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +517,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
public ListenableFuture<Blob> getBlob(final String containerName, final String key, GetOptions options) {
|
public ListenableFuture<Blob> getBlob(final String containerName, final String key, GetOptions options) {
|
||||||
logger.debug("Retrieving blob with key %s from container %s", key, containerName);
|
logger.debug("Retrieving blob with key %s from container %s", key, containerName);
|
||||||
// If the container doesn't exist, an exception is thrown
|
// If the container doesn't exist, an exception is thrown
|
||||||
if (!containerExistsSyncImpl(containerName)) {
|
if (!storageStrategy.containerExists(containerName)) {
|
||||||
logger.debug("Container %s does not exist", containerName);
|
logger.debug("Container %s does not exist", containerName);
|
||||||
return immediateFailedFuture(cnfe(containerName));
|
return immediateFailedFuture(cnfe(containerName));
|
||||||
}
|
}
|
||||||
|
@ -601,17 +605,6 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Each container is a directory, so in order to check if a container exists
|
|
||||||
* the corresponding directory must exists. Synchronous implementation
|
|
||||||
*
|
|
||||||
* @param containerName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private boolean containerExistsSyncImpl(String containerName) {
|
|
||||||
return storageStrategy.containerExists(containerName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the object MD5 and returns it as eTag
|
* Calculates the object MD5 and returns it as eTag
|
||||||
*
|
*
|
||||||
|
@ -633,7 +626,7 @@ public class FilesystemAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
@Override
|
@Override
|
||||||
protected boolean deleteAndVerifyContainerGone(final String container) {
|
protected boolean deleteAndVerifyContainerGone(final String container) {
|
||||||
storageStrategy.deleteContainer(container);
|
storageStrategy.deleteContainer(container);
|
||||||
return containerExistsSyncImpl(container);
|
return storageStrategy.containerExists(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -565,8 +565,12 @@ public class FilesystemAsyncBlobStoreTest {
|
||||||
|
|
||||||
// when location doesn't exists
|
// when location doesn't exists
|
||||||
blobKey = TestUtils.createRandomBlobKey();
|
blobKey = TestUtils.createRandomBlobKey();
|
||||||
result = blobStore.blobExists(CONTAINER_NAME, blobKey);
|
try {
|
||||||
assertFalse(result, "Blob exists");
|
blobStore.blobExists(CONTAINER_NAME, blobKey);
|
||||||
|
fail();
|
||||||
|
} catch (ContainerNotFoundException cnfe) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
|
||||||
// when location exists
|
// when location exists
|
||||||
blobStore.createContainerInLocation(null, CONTAINER_NAME);
|
blobStore.createContainerInLocation(null, CONTAINER_NAME);
|
||||||
|
|
|
@ -128,6 +128,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
protected final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
|
protected final HttpGetOptionsListToGetOptions httpGetOptionsConverter;
|
||||||
protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
protected final IfDirectoryReturnNameStrategy ifDirectoryReturnName;
|
||||||
protected final Factory blobFactory;
|
protected final Factory blobFactory;
|
||||||
|
protected final TransientStorageStrategy storageStrategy;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected TransientAsyncBlobStore(BlobStoreContext context,
|
protected TransientAsyncBlobStore(BlobStoreContext context,
|
||||||
|
@ -152,6 +153,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
this.ifDirectoryReturnName = ifDirectoryReturnName;
|
this.ifDirectoryReturnName = ifDirectoryReturnName;
|
||||||
getContainerToLocation().put("stub", defaultLocation.get());
|
getContainerToLocation().put("stub", defaultLocation.get());
|
||||||
getContainerToBlobs().put("stub", new ConcurrentHashMap<String, Blob>());
|
getContainerToBlobs().put("stub", new ConcurrentHashMap<String, Blob>());
|
||||||
|
this.storageStrategy = new TransientStorageStrategy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,8 +248,9 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContainerNotFoundException cnfe(final String name) {
|
private ContainerNotFoundException cnfe(final String name) {
|
||||||
return new ContainerNotFoundException(name, String.format("container %s not in %s", name, getContainerToBlobs()
|
return new ContainerNotFoundException(name, String.format(
|
||||||
.keySet()));
|
"container %s not in %s", name,
|
||||||
|
storageStrategy.getAllContainerNames()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
|
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
|
||||||
|
@ -285,9 +288,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> removeBlob(final String container, final String key) {
|
public ListenableFuture<Void> removeBlob(final String container, final String key) {
|
||||||
if (getContainerToBlobs().containsKey(container)) {
|
storageStrategy.removeBlob(container, key);
|
||||||
getContainerToBlobs().get(container).remove(key);
|
|
||||||
}
|
|
||||||
return immediateFuture(null);
|
return immediateFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,17 +306,15 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> deleteContainer(final String container) {
|
public ListenableFuture<Void> deleteContainer(final String container) {
|
||||||
if (getContainerToBlobs().containsKey(container)) {
|
deleteAndVerifyContainerGone(container);
|
||||||
getContainerToBlobs().remove(container);
|
|
||||||
}
|
|
||||||
return immediateFuture(null);
|
return immediateFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<Boolean> deleteContainerIfEmpty(final String container) {
|
public ListenableFuture<Boolean> deleteContainerIfEmpty(final String container) {
|
||||||
Boolean returnVal = true;
|
Boolean returnVal = true;
|
||||||
if (getContainerToBlobs().containsKey(container)) {
|
if (storageStrategy.containerExists(container)) {
|
||||||
if (getContainerToBlobs().get(container).size() == 0)
|
if (getContainerToBlobs().get(container).size() == 0)
|
||||||
getContainerToBlobs().remove(container);
|
storageStrategy.deleteContainer(container);
|
||||||
else
|
else
|
||||||
returnVal = false;
|
returnVal = false;
|
||||||
}
|
}
|
||||||
|
@ -327,7 +326,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> containerExists(final String containerName) {
|
public ListenableFuture<Boolean> containerExists(final String containerName) {
|
||||||
return immediateFuture(getContainerToBlobs().containsKey(containerName));
|
return immediateFuture(storageStrategy.containerExists(containerName));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -335,7 +334,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||||
Iterable<String> containers = getContainerToBlobs().keySet();
|
Iterable<String> containers = storageStrategy.getAllContainerNames();
|
||||||
|
|
||||||
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
|
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
|
||||||
containers, new Function<String, StorageMetadata>() {
|
containers, new Function<String, StorageMetadata>() {
|
||||||
|
@ -358,7 +357,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> createContainerInLocation(final Location location, final String name) {
|
public ListenableFuture<Boolean> createContainerInLocation(final Location location, final String name) {
|
||||||
if (getContainerToBlobs().containsKey(name)) {
|
if (storageStrategy.containerExists(name)) {
|
||||||
return immediateFuture(Boolean.FALSE);
|
return immediateFuture(Boolean.FALSE);
|
||||||
}
|
}
|
||||||
getContainerToBlobs().put(name, new ConcurrentHashMap<String, Blob>());
|
getContainerToBlobs().put(name, new ConcurrentHashMap<String, Blob>());
|
||||||
|
@ -542,10 +541,9 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> blobExists(final String containerName, final String key) {
|
public ListenableFuture<Boolean> blobExists(final String containerName, final String key) {
|
||||||
if (!getContainerToBlobs().containsKey(containerName))
|
if (!storageStrategy.containerExists(containerName))
|
||||||
return immediateFailedFuture(cnfe(containerName));
|
return immediateFailedFuture(cnfe(containerName));
|
||||||
Map<String, Blob> realContents = getContainerToBlobs().get(containerName);
|
return immediateFuture(storageStrategy.blobExists(containerName, key));
|
||||||
return immediateFuture(realContents.containsKey(key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -555,7 +553,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
public ListenableFuture<Blob> getBlob(final String containerName, final String key, GetOptions options) {
|
public ListenableFuture<Blob> getBlob(final String containerName, final String key, GetOptions options) {
|
||||||
logger.debug("Retrieving blob with key %s from container %s", key, containerName);
|
logger.debug("Retrieving blob with key %s from container %s", key, containerName);
|
||||||
// If the container doesn't exist, an exception is thrown
|
// If the container doesn't exist, an exception is thrown
|
||||||
if (!getContainerToBlobs().containsKey(containerName)) {
|
if (!storageStrategy.containerExists(containerName)) {
|
||||||
logger.debug("Container %s does not exist", containerName);
|
logger.debug("Container %s does not exist", containerName);
|
||||||
return immediateFailedFuture(cnfe(containerName));
|
return immediateFailedFuture(cnfe(containerName));
|
||||||
}
|
}
|
||||||
|
@ -660,8 +658,8 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean deleteAndVerifyContainerGone(final String container) {
|
protected boolean deleteAndVerifyContainerGone(final String container) {
|
||||||
getContainerToBlobs().remove(container);
|
storageStrategy.deleteContainer(container);
|
||||||
return getContainerToBlobs().containsKey(container);
|
return storageStrategy.containerExists(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConcurrentMap<String, Location> getContainerToLocation() {
|
private ConcurrentMap<String, Location> getContainerToLocation() {
|
||||||
|
@ -681,4 +679,29 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
throw new UnsupportedOperationException("publicRead");
|
throw new UnsupportedOperationException("publicRead");
|
||||||
return createContainerInLocation(location, container);
|
return createContainerInLocation(location, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TransientStorageStrategy {
|
||||||
|
public Iterable<String> getAllContainerNames() {
|
||||||
|
return getContainerToBlobs().keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containerExists(final String containerName) {
|
||||||
|
return getContainerToBlobs().containsKey(containerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteContainer(final String containerName) {
|
||||||
|
getContainerToBlobs().remove(containerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean blobExists(final String containerName, final String blobName) {
|
||||||
|
Map<String, Blob> map = containerToBlobs.get(containerName);
|
||||||
|
return map != null && map.containsKey(blobName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeBlob(final String containerName, final String blobName) {
|
||||||
|
if (storageStrategy.containerExists(containerName)) {
|
||||||
|
getContainerToBlobs().get(containerName).remove(blobName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue