package com.amazonaws.bigdatablog.s3index;
import static com.amazonaws.bigdatablog.s3index.Util.prompt;
import static java.util.stream.Collectors.toList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion;
import com.amazonaws.services.s3.model.ObjectListing;
public class TruncateBucket {
private static final AmazonS3 s3 = new AmazonS3Client();
private final String bucketName;
private final BlockingQueue<String> keys = new LinkedBlockingQueue<>();
private volatile boolean complete = false;
public TruncateBucket(String bucketName) {
this.bucketName = bucketName;
}
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("WARNING: This will indiscriminately delete every object in a given bucket. This operation cannot be undone.");
final String bucketName = prompt("Bucket");
if (!"yes".equals(prompt("Are you sure you want to delete all objects in bucket " + bucketName + "? (type 'yes' to continue)"))) {
System.out.println("Aborting...");
return;
}
final TruncateBucket truncater = new TruncateBucket(bucketName);
truncater.truncate();
ObjectListing results;
do {
results = s3.listObjects(bucketName);
final List<KeyVersion> keys = results.getObjectSummaries().stream()
.map((k) -> new KeyVersion(k.getKey()))
.collect(toList());
final DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName).withKeys(keys);
s3.deleteObjects(deleteRequest);
} while (results.isTruncated());
}
private void truncate() throws InterruptedException {
new Thread(this::listKeys).start();
final Collection<String> keyBuffer = new ArrayList<>(1000);
while(true) {
final String key = keys.poll(1, TimeUnit.SECONDS);
if (key == null) {
continue;
}
keys.add(key);
keys.drainTo(keyBuffer, 999);
if (keys.isEmpty() && complete) {
return;
} else {
delete(keyBuffer);
}
}
}
private void delete(Collection<String> keyBuffer) {
final String[] keyArray = keyBuffer.toArray(new String[keyBuffer.size()]);
final DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName).withKeys(keyArray);
s3.deleteObjects(deleteRequest);
}
private void listKeys() {
ObjectListing listing = s3.listObjects(bucketName);
addKeys(listing);
while (listing.isTruncated()) {
listing = s3.listNextBatchOfObjects(listing);
}
complete = true;
}
private void addKeys(ObjectListing listing) {
keys.addAll(listing.getObjectSummaries().stream().map((o) -> o.getKey()).collect(toList()));
}
}