JCLOUDS-930: Handle subdir entries correctly.

When listing blobs, Swift returns an array of "subdir" entries for
every common prefix. The openstack-swift provider needs to process
such entries and add them to the result set. The subdir array is an
array of strings, so additional metadata needs to be added to the
objects (bogus ETag, bogus LastModifiedDate, and so on).

When directory marker blobs are used, this means that potential _two_
entries are generated for every directory if:
1. the delimiter is set and matches the directory blob (e.g. dir/ and
   delimiter /)
2. there are objects under the directory name (e.g. dir/blob), which
   will result in results that include common prefixes (subdir)

In the above example, we should expect two results: "dir" and "dir/"
representing the directory marker blob and the common prefix,
respectively.

This is caught in the testDirectory integration test.

The patch changes the behavior of the Swift provider to correctly
handle the results in the subdir stanza and changes the test to expect
the directory marker to be returned in the list.
This commit is contained in:
Timur Alperovich 2015-07-01 17:50:30 -07:00 committed by Andrew Gaul
parent 1c1cfffd5d
commit 6d27fbb18a
2 changed files with 14 additions and 2 deletions

View File

@ -46,6 +46,7 @@ public class ParseObjectListFromResponse implements Function<HttpResponse, Objec
private static final class InternalObject {
String name;
String hash;
String subdir;
long bytes;
String content_type;
Date last_modified;
@ -66,11 +67,14 @@ public class ParseObjectListFromResponse implements Function<HttpResponse, Objec
@Override
public ObjectList apply(HttpResponse from) {
List<SwiftObject> objects = Lists.transform(json.apply(from), toSwiftObject);
Container container = parseContainer.apply(from);
return ObjectList.create(objects, container);
}
static class ToSwiftObject implements Function<InternalObject, SwiftObject> {
private static final String SUBDIR_ETAG = "deadbeef";
private final String containerUri;
ToSwiftObject(String containerUri) {
@ -79,6 +83,14 @@ public class ParseObjectListFromResponse implements Function<HttpResponse, Objec
@Override
public SwiftObject apply(InternalObject input) {
if (input.subdir != null) {
return SwiftObject.builder()
.uri(uriBuilder(containerUri).clearQuery().appendPath(input.subdir).build())
.name(input.subdir)
.etag(SUBDIR_ETAG)
.payload(payload(input.bytes, input.hash, "application/directory", input.expires))
.lastModified(new Date(0)).build();
}
return SwiftObject.builder()
.uri(uriBuilder(containerUri).clearQuery().appendPath(input.name).build())
.name(input.name)

View File

@ -234,9 +234,9 @@ public class BaseContainerIntegrationTest extends BaseBlobStoreIntegrationTest {
awaitConsistency();
container = view.getBlobStore().list(containerName);
// we should still have only the directory under root
// we should get back the subdir entry and the directory marker
assert container.getNextMarker() == null;
assert container.size() == 1 : container;
assertThat(container).hasSize(2);
container = view.getBlobStore().list(containerName, inDirectory(directory));
// we should have only the 10 items under the directory