Skip to content

Commit b999e40

Browse files
authored
Merge pull request #104 from EMCECS/feature-bucket-delete-improvement
Feature bucket delete improvement
2 parents 8937fd5 + 2108227 commit b999e40

File tree

8 files changed

+538
-1
lines changed

8 files changed

+538
-1
lines changed

src/main/java/com/emc/object/s3/S3Client.java

+10
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,16 @@ public interface S3Client {
110110
*/
111111
void deleteBucket(String bucketName);
112112

113+
/**
114+
* Deletes <code>bucketName</code>. The bucket could contain objects and versions before it can be deleted
115+
*/
116+
void deleteBucket(DeleteBucketRequest request);
117+
118+
/**
119+
* Gets status of background bucket cleanup tasks for <code>bucketName</code> if present
120+
*/
121+
BucketDeletionStatus getBucketDeletionStatus(String bucketName);
122+
113123
/**
114124
* Sets the specified ACL on <code>bucketName</code>
115125
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
package com.emc.object.s3.bean;
2+
3+
import javax.xml.bind.annotation.XmlElement;
4+
import javax.xml.bind.annotation.XmlRootElement;
5+
import javax.xml.bind.annotation.XmlType;
6+
import java.util.ArrayList;
7+
import java.util.Date;
8+
import java.util.List;
9+
10+
@XmlRootElement(name = "EmptyBucketStatus")
11+
public class BucketDeletionStatus {
12+
13+
private String status;
14+
15+
private Date created;
16+
17+
private Date lastUpdated;
18+
19+
private Long entriesDeleted;
20+
21+
private Long failedToDeleteRetention;
22+
23+
private Long failedToDeletePermission;
24+
25+
private Long failedToDeleteDangling;
26+
27+
private Long failedToDeleteOther;
28+
29+
private Long approximateObjectCount;
30+
31+
private Double approximateTotalSize;
32+
33+
private String approximateTotalSizeUnitString;
34+
35+
private String message;
36+
37+
/**
38+
* Overall status of the bucket delete task
39+
* Valid values: PENDING, IN_PROGRESS, POST_PROCESSING, DONE, FAILED, ABORT_IN_PROGRESS, ABORTED
40+
* <br>
41+
* PENDING - The task has been created and will start execution once it is successfully configured.
42+
* <br>
43+
* IN_PROGRESS - The task is executing normally.
44+
* <br>
45+
* POST_PROCESSING - The task is finsished processing and is finalizing before moving to the DONE or FAILED state.
46+
* <br>
47+
* DONE - The task successfully completed and the bucket was deleted.
48+
* <br>
49+
* ABORT_IN_PROGRESS - The tasks is aborting and is finalizing before moving to the ABORTED state.
50+
* <br>
51+
* ABORTED - The task was stopped before it could complete and should be retried.
52+
* <br>
53+
* FAILED - The task completed but not all items associated with the bucket could be removed.
54+
* <br>
55+
* <br>
56+
* When the status is FAILED the failed_to_delete_n counts give an indication of why certain items could not be removed by the task.
57+
*
58+
*/
59+
@XmlElement(name="Status")
60+
public String getStatus() {
61+
return status;
62+
}
63+
64+
/**
65+
* {@link BucketDeletionStatus#getStatus}
66+
*/
67+
public void setStatus(String status) {
68+
this.status = status;
69+
}
70+
71+
/**
72+
* Timestamp when the operation was created
73+
* @valid Date in ISO 8601 format
74+
*/
75+
@XmlElement(name="Created")
76+
public Date getCreated() {
77+
return created;
78+
}
79+
80+
/**
81+
* {@link BucketDeletionStatus#getCreated}
82+
*/
83+
public void setCreated(Date created) {
84+
this.created = created;
85+
}
86+
87+
/**
88+
* Timestamp of the last time the operation status was updated
89+
* @valid Date in ISO 8601 format
90+
*/
91+
@XmlElement(name = "LastUpdated")
92+
public Date getLastUpdated() {
93+
return lastUpdated;
94+
}
95+
96+
/**
97+
* {@link BucketDeletionStatus#getLastUpdated}
98+
*/
99+
public void setLastUpdated(Date lastUpdated) {
100+
this.lastUpdated = lastUpdated;
101+
}
102+
103+
/**
104+
* Number of entries deleted
105+
* @valid none
106+
*/
107+
@XmlElement(name = "EntriesDeleted")
108+
public Long getEntriesDeleted() {
109+
return entriesDeleted;
110+
}
111+
112+
/**
113+
* {@link BucketDeletionStatus#getEntriesDeleted}
114+
*/
115+
public void setEntriesDeleted(Long entriesDeleted) {
116+
this.entriesDeleted = entriesDeleted;
117+
}
118+
119+
/**
120+
* Number of entries unable to delete due to retention
121+
* @valid none
122+
*/
123+
@XmlElement(name = "FailedToDeleteDueToRetention")
124+
public Long getFailedToDeleteRetention() {
125+
return failedToDeleteRetention;
126+
}
127+
128+
/**
129+
* {@link BucketDeletionStatus#getFailedToDeleteRetention}
130+
*/
131+
public void setFailedToDeleteRetention(Long failedToDeleteRetention) {
132+
this.failedToDeleteRetention = failedToDeleteRetention;
133+
}
134+
135+
/**
136+
* Number of entries failed to delete due to permission
137+
* @valid none
138+
*/
139+
@XmlElement(name = "FailedToDeleteDueToPermission")
140+
public Long getFailedToDeletePermission() {
141+
return failedToDeletePermission;
142+
}
143+
144+
/**
145+
* {@link BucketDeletionStatus#getFailedToDeletePermission}
146+
*/
147+
public void setFailedToDeletePermission(Long failedToDeletePermission) {
148+
this.failedToDeletePermission = failedToDeletePermission;
149+
}
150+
151+
/**
152+
* Number of entries failed to delete due to failed dangling cleanup
153+
* @valid none
154+
*/
155+
@XmlElement(name = "FailedToDeleteDueToDangling")
156+
public Long getFailedToDeleteDangling() {
157+
return failedToDeleteDangling;
158+
}
159+
160+
/**
161+
* {@link BucketDeletionStatus#getFailedToDeleteDangling}
162+
*/
163+
public void setFailedToDeleteDangling(Long failedToDeleteDangling) {
164+
this.failedToDeleteDangling = failedToDeleteDangling;
165+
}
166+
167+
/**
168+
* Number of entries failed to delete due to other reasons
169+
* @valid none
170+
*/
171+
@XmlElement(name = "FailedToDeleteDueToOther")
172+
public Long getFailedToDeleteOther() {
173+
return failedToDeleteOther;
174+
}
175+
176+
/**
177+
* {@link BucketDeletionStatus#getFailedToDeleteOther}
178+
*/
179+
public void setFailedToDeleteOther(Long failedToDeleteOther) {
180+
this.failedToDeleteOther = failedToDeleteOther;
181+
}
182+
183+
/**
184+
* Approximate count of objects in the bucket before deletion
185+
* @valid none
186+
*/
187+
@XmlElement(name = "")
188+
public Long getApproximateObjectCount() {
189+
return approximateObjectCount;
190+
}
191+
192+
/**
193+
* {@link BucketDeletionStatus#getApproximateObjectCount}
194+
*/
195+
public void setApproximateObjectCount(Long approximateObjectCount) {
196+
this.approximateObjectCount = approximateObjectCount;
197+
}
198+
199+
/**
200+
* Approximate total size of the bucket before deletion
201+
* @valid none
202+
*/
203+
@XmlElement(name = "ApproximateTotalSize")
204+
public Double getApproximateTotalSize() {
205+
return approximateTotalSize;
206+
}
207+
208+
/**
209+
* {@link BucketDeletionStatus#getApproximateTotalSize}
210+
*/
211+
public void setApproximateTotalSize(Double approximateTotalSize) {
212+
this.approximateTotalSize = approximateTotalSize;
213+
}
214+
215+
/**
216+
* Unit of the approximate bucket total size
217+
* @valid none
218+
*/
219+
@XmlElement(name = "ApproximateTotalSizeUnitString")
220+
public String getApproximateTotalSizeUnitString() {
221+
return approximateTotalSizeUnitString;
222+
}
223+
224+
/**
225+
* {@link BucketDeletionStatus#getApproximateTotalSizeUnitString}
226+
*/
227+
public void setApproximateTotalSizeUnitString(String approximateTotalSizeUnitString) {
228+
this.approximateTotalSizeUnitString = approximateTotalSizeUnitString;
229+
}
230+
231+
/**
232+
* Optional additional information about the status
233+
* @valid none
234+
*/
235+
@XmlElement(name = "Message")
236+
public String getMessage() {
237+
return message;
238+
}
239+
240+
/**
241+
* {@link BucketDeletionStatus#getMessage}
242+
*/
243+
public void setMessage(String message) {
244+
this.message = message;
245+
}
246+
247+
public BucketDeletionStatus withStatus(String status) {
248+
setStatus(status);
249+
return this;
250+
}
251+
252+
public BucketDeletionStatus withCreated(Date created) {
253+
setCreated(created);
254+
return this;
255+
}
256+
257+
public BucketDeletionStatus withLastUpdated(Date lastUpdated) {
258+
setLastUpdated(lastUpdated);
259+
return this;
260+
}
261+
262+
public BucketDeletionStatus withEntriesDeleted(Long entriesDeleted) {
263+
setEntriesDeleted(entriesDeleted);
264+
return this;
265+
}
266+
267+
public BucketDeletionStatus withFailedToDeleteRetention(Long failedToDeleteRetention) {
268+
setFailedToDeleteRetention(failedToDeleteRetention);
269+
return this;
270+
}
271+
272+
public BucketDeletionStatus withFailedToDeletePermission(Long failedToDeletePermission) {
273+
setFailedToDeletePermission(failedToDeletePermission);
274+
return this;
275+
}
276+
277+
public BucketDeletionStatus withFailedToDeleteDangling(Long failedToDeleteDangling) {
278+
setFailedToDeleteDangling(failedToDeleteDangling);
279+
return this;
280+
}
281+
282+
public BucketDeletionStatus withFailedToDeleteOther(Long failedToDeleteOther) {
283+
setFailedToDeleteOther(failedToDeleteOther);
284+
return this;
285+
}
286+
287+
public BucketDeletionStatus withApproximateObjectCount(Long approximateObjectCount) {
288+
setApproximateObjectCount(approximateObjectCount);
289+
return this;
290+
}
291+
292+
public BucketDeletionStatus withApproximateTotalSize(Double approximateTotalSize) {
293+
setApproximateTotalSize(approximateTotalSize);
294+
return this;
295+
}
296+
297+
public BucketDeletionStatus withApproximateTotalSizeUnitString(String approximateTotalSizeUnitString) {
298+
setApproximateTotalSizeUnitString(approximateTotalSizeUnitString);
299+
return this;
300+
}
301+
302+
public BucketDeletionStatus withMessage(String message) {
303+
setMessage(message);
304+
return this;
305+
}
306+
307+
}

src/main/java/com/emc/object/s3/jersey/S3JerseyClient.java

+10
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,16 @@ public void deleteBucket(String bucketName) {
332332
executeAndClose(client, new GenericBucketRequest(Method.DELETE, bucketName, null));
333333
}
334334

335+
@Override
336+
public void deleteBucket(DeleteBucketRequest request) {
337+
executeAndClose(client, request);
338+
}
339+
340+
@Override
341+
public BucketDeletionStatus getBucketDeletionStatus(String bucketName) {
342+
return executeRequest(client, new GetBucketDeletionStatusRequest(bucketName), BucketDeletionStatus.class);
343+
}
344+
335345
@Override
336346
public void setBucketAcl(String bucketName, AccessControlList acl) {
337347
setBucketAcl(new SetBucketAclRequest(bucketName).withAcl(acl));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.emc.object.s3.request;
2+
3+
import com.emc.object.Method;
4+
import com.emc.object.util.RestUtil;
5+
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
public class DeleteBucketRequest extends GenericBucketRequest {
10+
11+
private boolean recursivelyDeleteAllData;
12+
public DeleteBucketRequest(String bucketName, boolean recursivelyDeleteAllData) {
13+
super(Method.DELETE, bucketName, null);
14+
this.recursivelyDeleteAllData = recursivelyDeleteAllData;
15+
}
16+
17+
public DeleteBucketRequest(String bucketName) {
18+
super(Method.DELETE, bucketName, null);
19+
}
20+
21+
@Override
22+
public Map<String, List<Object>> getHeaders() {
23+
Map<String, List<Object>> headers = super.getHeaders();
24+
if (recursivelyDeleteAllData)
25+
RestUtil.putSingle(headers, RestUtil.EMC_EMPTY_BUCKET, "true");
26+
return headers;
27+
}
28+
29+
/**
30+
* It is the trigger to use the new bucket deletion feature.
31+
* The current delete operation is a synchronous operation, when recursivelyDeleteAllData is default set to false..
32+
* When recursivelyDeleteAllData comes to true, the request becomes asynchronous and will return immediately.
33+
* The bucket will be marked as "delete in progress". The bucket will be read-only through S3 and will not allow reads/writes through NFS (for FS bucket).
34+
* Background tasks will be initiated across all of the associated zones and tables to remove objects/versions associated with the buckets.
35+
* Once all tasks have completed the bucket will be deleted from the system.
36+
* It must be noted that the issue of object lock and governance must not be overlooked for such an operation.
37+
* It must be noted that the operation will delete all objects and data in the bucket and it cannot be undone.
38+
* It is only supported on ECS version 3.8 or above.
39+
*/
40+
public boolean isRecursivelyDeleteAllData() {
41+
return recursivelyDeleteAllData;
42+
}
43+
44+
/**
45+
* {@link DeleteBucketRequest#isRecursivelyDeleteAllData}
46+
*/
47+
public void setRecursivelyDeleteAllData(boolean recursivelyDeleteAllData) {
48+
this.recursivelyDeleteAllData = recursivelyDeleteAllData;
49+
}
50+
51+
public DeleteBucketRequest withRecursivelyDeleteAllData(boolean recursivelyDeleteAllData) {
52+
setRecursivelyDeleteAllData(recursivelyDeleteAllData);
53+
return this;
54+
}
55+
56+
}

0 commit comments

Comments
 (0)