Skip to content

Commit 7ff978e

Browse files
author
Timur Alperovich
committed
Use removeBlobs() for bulk-delete.
We should use removeBlobs() for bulk-delete. The change deletes blobs en-masse. Further, we no longer will perform a HEAD on every blob, as that's fairly expensive. Fixes #38
1 parent b2c46e6 commit 7ff978e

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

src/main/java/com/bouncestorage/swiftproxy/v1/AccountResource.java

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.io.IOException;
2525
import java.io.InputStreamReader;
2626
import java.util.ArrayList;
27+
import java.util.Collection;
2728
import java.util.List;
2829
import java.util.Objects;
2930
import java.util.Optional;
@@ -56,7 +57,9 @@
5657
import com.fasterxml.jackson.annotation.JsonProperty;
5758
import com.fasterxml.jackson.core.JsonProcessingException;
5859
import com.fasterxml.jackson.databind.ObjectMapper;
60+
import com.google.common.collect.ArrayListMultimap;
5961
import com.google.common.collect.Lists;
62+
import com.google.common.collect.Multimap;
6063

6164
import org.glassfish.grizzly.http.server.Request;
6265
import org.jclouds.blobstore.BlobStore;
@@ -151,33 +154,45 @@ public BulkDeleteResult bulkDelete(@NotNull @PathParam("account") String account
151154
}
152155

153156
BulkDeleteResult result = new BulkDeleteResult();
157+
Multimap<String, String> removeBlobsMap = ArrayListMultimap.create();
158+
List<String> deleteContainers = new ArrayList<>();
154159
for (String objectContainer : objects) {
155-
try {
156-
if (objectContainer.startsWith("/")) {
157-
objectContainer = objectContainer.substring(1);
158-
}
159-
int separatorIndex = objectContainer.indexOf('/');
160-
if (separatorIndex < 0) {
161-
blobStore.deleteContainer(objectContainer.substring(1));
162-
result.numberDeleted += 1;
163-
continue;
164-
}
165-
String container = objectContainer.substring(0, separatorIndex);
166-
String object = objectContainer.substring(separatorIndex + 1);
160+
if (objectContainer.startsWith("/")) {
161+
objectContainer = objectContainer.substring(1);
162+
}
163+
int separatorIndex = objectContainer.indexOf('/');
164+
if (separatorIndex < 0) {
165+
deleteContainers.add(objectContainer.substring(1));
166+
continue;
167+
}
168+
String container = objectContainer.substring(0, separatorIndex);
169+
String object = objectContainer.substring(separatorIndex + 1);
170+
removeBlobsMap.put(container, object);
171+
}
167172

168-
if (!blobStore.blobExists(container, object)) {
169-
result.numberNotFound += 1;
170-
} else {
171-
blobStore.removeBlob(container, object);
172-
result.numberDeleted += 1;
173-
}
173+
removeBlobsMap.keySet().forEach(container -> {
174+
Collection<String> blobs = removeBlobsMap.get(container);
175+
try {
176+
blobStore.removeBlobs(container, blobs);
177+
result.numberDeleted += blobs.size();
178+
} catch (ContainerNotFoundException e) {
179+
result.numberNotFound += blobs.size();
180+
} catch (Exception e) {
181+
logger.debug("Failed to remove blobs: " + e.getMessage(), e);
182+
blobs.forEach(blob -> result.errors.add(container + "/" + blob));
183+
}
184+
});
185+
deleteContainers.forEach(container -> {
186+
try {
187+
blobStore.deleteContainer(container);
188+
result.numberDeleted += 1;
174189
} catch (ContainerNotFoundException e) {
175190
result.numberNotFound += 1;
176191
} catch (Exception e) {
177-
e.printStackTrace();
178-
result.errors.add(objectContainer);
192+
logger.debug("Failed to delete container " + container + ": " + e.getMessage(), e);
193+
result.errors.add(container);
179194
}
180-
}
195+
});
181196

182197
if (result.errors.isEmpty()) {
183198
result.responseStatus = Response.Status.OK.toString();

0 commit comments

Comments
 (0)