From 52aa43bdcd4af98b30aa0dce4f536d44d7f9e84b Mon Sep 17 00:00:00 2001 From: Timur Alperovich Date: Fri, 12 Jun 2015 17:52:37 -0700 Subject: [PATCH] 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 --- .../swiftproxy/v1/AccountResource.java | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/bouncestorage/swiftproxy/v1/AccountResource.java b/src/main/java/com/bouncestorage/swiftproxy/v1/AccountResource.java index 3363179..dff0a6c 100644 --- a/src/main/java/com/bouncestorage/swiftproxy/v1/AccountResource.java +++ b/src/main/java/com/bouncestorage/swiftproxy/v1/AccountResource.java @@ -18,13 +18,16 @@ import static java.util.Objects.requireNonNull; +import static com.google.common.base.Throwables.getStackTraceAsString; import static com.google.common.base.Throwables.propagate; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -151,6 +154,8 @@ public BulkDeleteResult bulkDelete(@NotNull @PathParam("account") String account } BulkDeleteResult result = new BulkDeleteResult(); + Map> removeBlobsMap = new HashMap<>(); + List deleteContainers = new ArrayList<>(); for (String objectContainer : objects) { try { if (objectContainer.startsWith("/")) { @@ -158,27 +163,50 @@ public BulkDeleteResult bulkDelete(@NotNull @PathParam("account") String account } int separatorIndex = objectContainer.indexOf('/'); if (separatorIndex < 0) { - blobStore.deleteContainer(objectContainer.substring(1)); - result.numberDeleted += 1; + deleteContainers.add(objectContainer.substring(1)); continue; } String container = objectContainer.substring(0, separatorIndex); String object = objectContainer.substring(separatorIndex + 1); - if (!blobStore.blobExists(container, object)) { - result.numberNotFound += 1; - } else { - blobStore.removeBlob(container, object); - result.numberDeleted += 1; + if (!removeBlobsMap.containsKey(container)) { + removeBlobsMap.put(container, new ArrayList<>()); } + removeBlobsMap.get(container).add(object); } catch (ContainerNotFoundException e) { result.numberNotFound += 1; } catch (Exception e) { - e.printStackTrace(); + logger.error(e.toString()); + logger.debug(getStackTraceAsString(e)); result.errors.add(objectContainer); } } + removeBlobsMap.forEach((container, blobList) -> { + try { + blobStore.removeBlobs(container, blobList); + result.numberDeleted += blobList.size(); + } catch (ContainerNotFoundException e) { + result.numberNotFound += blobList.size(); + } catch (Exception e) { + logger.error(e.toString()); + logger.debug(getStackTraceAsString(e)); + blobList.forEach(blob -> result.errors.add(container + "/" + blob)); + } + }); + deleteContainers.forEach(container -> { + try { + blobStore.deleteContainer(container); + result.numberDeleted += 1; + } catch (ContainerNotFoundException e) { + result.numberNotFound += 1; + } catch (Exception e) { + logger.error(e.toString()); + logger.debug(getStackTraceAsString(e)); + result.errors.add(container); + } + }); + if (result.errors.isEmpty()) { result.responseStatus = Response.Status.OK.toString(); return result;