kopia lustrzana https://github.com/gaul/s3proxy
rodzic
e05343d986
commit
b0e119a99f
|
@ -39,11 +39,13 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSortedSet;
|
||||||
import com.google.common.hash.HashCode;
|
import com.google.common.hash.HashCode;
|
||||||
import com.google.common.hash.Hashing;
|
import com.google.common.hash.Hashing;
|
||||||
import com.google.common.hash.HashingInputStream;
|
import com.google.common.hash.HashingInputStream;
|
||||||
|
@ -141,7 +143,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PageSet<? extends StorageMetadata> list() {
|
public PageSet<? extends StorageMetadata> list() {
|
||||||
var set = ImmutableSet.<StorageMetadata>builder();
|
var set = ImmutableSortedSet.<StorageMetadata>naturalOrder();
|
||||||
try (var stream = Files.newDirectoryStream(fs.getPath(""))) {
|
try (var stream = Files.newDirectoryStream(fs.getPath(""))) {
|
||||||
for (var path : stream) {
|
for (var path : stream) {
|
||||||
var attr = Files.readAttributes(path,
|
var attr = Files.readAttributes(path,
|
||||||
|
@ -184,39 +186,52 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
||||||
prefix = "";
|
prefix = "";
|
||||||
}
|
}
|
||||||
prefix = "/" + container + "/" + prefix;
|
prefix = "/" + container + "/" + prefix;
|
||||||
var set = ImmutableSet.<StorageMetadata>builder();
|
var set = ImmutableSortedSet.<StorageMetadata>naturalOrder();
|
||||||
try {
|
try {
|
||||||
listHelper(set, /*count=*/ 0, options.getMaxResults(),
|
listHelper(set, container, dirPrefix, prefix, delimiter);
|
||||||
container, dirPrefix, prefix, delimiter,
|
var sorted = set.build();
|
||||||
options.getMarker());
|
if (options.getMarker() != null) {
|
||||||
|
for (var blob : sorted) {
|
||||||
|
if (blob.getName().compareTo(options.getMarker()) > 0) {
|
||||||
|
sorted = sorted.tailSet(blob);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String marker = null;
|
||||||
|
if (options.getMaxResults() != null) {
|
||||||
|
// TODO: efficiency?
|
||||||
|
var temp = ImmutableSortedSet.copyOf(sorted.stream().limit(options.getMaxResults().intValue()).collect(Collectors.toSet()));
|
||||||
|
if (!temp.isEmpty()) {
|
||||||
|
var next = sorted.higher(temp.last());
|
||||||
|
if (next != null) {
|
||||||
|
marker = temp.last().getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sorted = temp;
|
||||||
|
}
|
||||||
|
return new PageSetImpl<StorageMetadata>(sorted, marker);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
logger.error("unexpected exception", ioe);
|
logger.error("unexpected exception", ioe);
|
||||||
throw new RuntimeException(ioe);
|
throw new RuntimeException(ioe);
|
||||||
}
|
}
|
||||||
return new PageSetImpl<StorageMetadata>(set.build(), null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: marker
|
private static void listHelper(ImmutableSortedSet.Builder<StorageMetadata> builder,
|
||||||
private static int listHelper(ImmutableSet.Builder<StorageMetadata> builder,
|
String container, Path parent, String prefix, String delimiter)
|
||||||
int count, Integer maxResults, String container, Path parent, String prefix,
|
throws IOException {
|
||||||
String delimiter, String marker) throws IOException {
|
|
||||||
logger.debug("recursing at: {} with prefix: {}", parent, prefix);
|
logger.debug("recursing at: {} with prefix: {}", parent, prefix);
|
||||||
if (!Files.isDirectory(parent)) { // TODO: TOCTOU
|
if (!Files.isDirectory(parent)) { // TODO: TOCTOU
|
||||||
return count;
|
return;
|
||||||
}
|
}
|
||||||
try (var stream = Files.newDirectoryStream(parent)) {
|
try (var stream = Files.newDirectoryStream(parent)) {
|
||||||
for (var path : stream) {
|
for (var path : stream) {
|
||||||
if (maxResults != null && count == maxResults) {
|
|
||||||
// TODO: this is wrong -- return all results, sort, and limit in caller to produce marker
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug("examining: {}", path);
|
logger.debug("examining: {}", path);
|
||||||
if (!path.toString().startsWith(prefix.substring(1))) {
|
if (!path.toString().startsWith(prefix.substring(1))) {
|
||||||
continue;
|
continue;
|
||||||
} else if (Files.isDirectory(path)) {
|
} else if (Files.isDirectory(path)) {
|
||||||
if (!"/".equals(delimiter)) {
|
if (!"/".equals(delimiter)) {
|
||||||
count += listHelper(builder, count, maxResults, container, path, prefix, delimiter, marker);
|
listHelper(builder, container, path, prefix, delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a prefix if the directory blob exists or if the delimiter causes us not to recuse.
|
// Add a prefix if the directory blob exists or if the delimiter causes us not to recuse.
|
||||||
|
@ -230,7 +245,6 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
||||||
/*eTag=*/ null, /*creationTime=*/ null,
|
/*eTag=*/ null, /*creationTime=*/ null,
|
||||||
/*lastModifiedTime=*/ null,
|
/*lastModifiedTime=*/ null,
|
||||||
Map.of(), /*size=*/ null, Tier.STANDARD));
|
Map.of(), /*size=*/ null, Tier.STANDARD));
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var name = path.toString().substring((container + "/").length());
|
var name = path.toString().substring((container + "/").length());
|
||||||
|
@ -263,14 +277,11 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
||||||
/*location=*/ null, /*uri=*/ null,
|
/*location=*/ null, /*uri=*/ null,
|
||||||
eTag, creationTime, lastModifiedTime,
|
eTag, creationTime, lastModifiedTime,
|
||||||
Map.of(), attr.size(), tier));
|
Map.of(), attr.size(), tier));
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (NoSuchFileException nsfe) {
|
} catch (NoSuchFileException nsfe) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1009,8 +1009,6 @@ public final class AwsSdkTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBlobListV2() throws Exception {
|
public void testBlobListV2() throws Exception {
|
||||||
assumeTrue(!blobStoreType.equals("transient-nio2")); // TODO:
|
|
||||||
|
|
||||||
var metadata = new ObjectMetadata();
|
var metadata = new ObjectMetadata();
|
||||||
metadata.setContentLength(BYTE_SOURCE.size());
|
metadata.setContentLength(BYTE_SOURCE.size());
|
||||||
for (int i = 1; i < 5; ++i) {
|
for (int i = 1; i < 5; ++i) {
|
||||||
|
|
Ładowanie…
Reference in New Issue