Support list markers in transient-nio2

References #697.
pull/733/head
Andrew Gaul 2024-11-23 16:48:12 -08:00
rodzic e05343d986
commit b0e119a99f
2 zmienionych plików z 33 dodań i 24 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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) {