Skip to content

Commit 2433e01

Browse files
committed
HDDS-4358: Delete : make delete an atomic operation (#1607)
1 parent 0d9a65b commit 2433e01

File tree

25 files changed

+755
-235
lines changed

25 files changed

+755
-235
lines changed

hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/OzoneBucket.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,21 @@ public Iterator<? extends OzoneKey> listKeys(String keyPrefix,
553553
* @throws IOException
554554
*/
555555
public void deleteKey(String key) throws IOException {
556-
proxy.deleteKey(volumeName, name, key);
556+
proxy.deleteKey(volumeName, name, key, false);
557+
}
558+
559+
/**
560+
* Ozone FS api to delete a directory. Sub directories will be deleted if
561+
* recursive flag is true, otherwise it will be non-recursive.
562+
*
563+
* @param key Name of the key to be deleted.
564+
* @param recursive recursive deletion of all sub path keys if true,
565+
* otherwise non-recursive
566+
* @throws IOException
567+
*/
568+
public void deleteDirectory(String key, boolean recursive)
569+
throws IOException {
570+
proxy.deleteKey(volumeName, name, key, recursive);
557571
}
558572

559573
/**

hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/protocol/ClientProtocol.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,12 @@ OzoneInputStream getKey(String volumeName, String bucketName, String keyName)
289289
* @param volumeName Name of the Volume
290290
* @param bucketName Name of the Bucket
291291
* @param keyName Name of the Key
292+
* @param recursive recursive deletion of all sub path keys if true,
293+
* otherwise non-recursive
292294
* @throws IOException
293295
*/
294-
void deleteKey(String volumeName, String bucketName, String keyName)
296+
void deleteKey(String volumeName, String bucketName, String keyName,
297+
boolean recursive)
295298
throws IOException;
296299

297300
/**

hadoop-ozone/client/src/main/java/org/apache/hadoop/ozone/client/rpc/RpcClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ public OzoneInputStream getKey(
747747

748748
@Override
749749
public void deleteKey(
750-
String volumeName, String bucketName, String keyName)
750+
String volumeName, String bucketName, String keyName, boolean recursive)
751751
throws IOException {
752752
verifyVolumeName(volumeName);
753753
verifyBucketName(bucketName);
@@ -756,6 +756,7 @@ public void deleteKey(
756756
.setVolumeName(volumeName)
757757
.setBucketName(bucketName)
758758
.setKeyName(keyName)
759+
.setRecursive(recursive)
759760
.build();
760761
ozoneManagerClient.deleteKey(keyArgs);
761762
}

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/exceptions/OMException.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,9 @@ public enum ResultCodes {
233233

234234
QUOTA_EXCEEDED,
235235

236-
QUOTA_ERROR
236+
QUOTA_ERROR,
237+
238+
DIRECTORY_NOT_EMPTY
237239

238240
}
239241
}

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyArgs.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,15 @@ public final class OmKeyArgs implements Auditable {
4848
private boolean refreshPipeline;
4949
private boolean sortDatanodesInPipeline;
5050
private List<OzoneAcl> acls;
51+
private boolean recursive;
5152

5253
@SuppressWarnings("parameternumber")
5354
private OmKeyArgs(String volumeName, String bucketName, String keyName,
5455
long dataSize, ReplicationType type, ReplicationFactor factor,
5556
List<OmKeyLocationInfo> locationInfoList, boolean isMultipart,
5657
String uploadID, int partNumber,
5758
Map<String, String> metadataMap, boolean refreshPipeline,
58-
List<OzoneAcl> acls, boolean sortDatanode) {
59+
List<OzoneAcl> acls, boolean sortDatanode, boolean recursive) {
5960
this.volumeName = volumeName;
6061
this.bucketName = bucketName;
6162
this.keyName = keyName;
@@ -70,6 +71,7 @@ private OmKeyArgs(String volumeName, String bucketName, String keyName,
7071
this.refreshPipeline = refreshPipeline;
7172
this.acls = acls;
7273
this.sortDatanodesInPipeline = sortDatanode;
74+
this.recursive = recursive;
7375
}
7476

7577
public boolean getIsMultipartKey() {
@@ -140,6 +142,10 @@ public boolean getSortDatanodes() {
140142
return sortDatanodesInPipeline;
141143
}
142144

145+
public boolean isRecursive() {
146+
return recursive;
147+
}
148+
143149
@Override
144150
public Map<String, String> toAuditMap() {
145151
Map<String, String> auditMap = new LinkedHashMap<>();
@@ -198,6 +204,7 @@ public static class Builder {
198204
private boolean refreshPipeline;
199205
private boolean sortDatanodesInPipeline;
200206
private List<OzoneAcl> acls;
207+
private boolean recursive;
201208

202209
public Builder setVolumeName(String volume) {
203210
this.volumeName = volume;
@@ -274,11 +281,16 @@ public Builder setSortDatanodesInPipeline(boolean sort) {
274281
return this;
275282
}
276283

284+
public Builder setRecursive(boolean isRecursive) {
285+
this.recursive = isRecursive;
286+
return this;
287+
}
288+
277289
public OmKeyArgs build() {
278290
return new OmKeyArgs(volumeName, bucketName, keyName, dataSize, type,
279291
factor, locationInfoList, isMultipartKey, multipartUploadID,
280292
multipartUploadPartNumber, metadata, refreshPipeline, acls,
281-
sortDatanodesInPipeline);
293+
sortDatanodesInPipeline, recursive);
282294
}
283295

284296
}

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/protocolPB/OzoneManagerProtocolClientSideTranslatorPB.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,8 @@ public void deleteKey(OmKeyArgs args) throws IOException {
741741
KeyArgs keyArgs = KeyArgs.newBuilder()
742742
.setVolumeName(args.getVolumeName())
743743
.setBucketName(args.getBucketName())
744-
.setKeyName(args.getKeyName()).build();
744+
.setKeyName(args.getKeyName())
745+
.setRecursive(args.isRecursive()).build();
745746
req.setKeyArgs(keyArgs);
746747

747748
OMRequest omRequest = createOMRequest(Type.DeleteKey)

hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/fs/ozone/TestOzoneFileSystem.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.apache.hadoop.fs.FileSystem;
3636
import org.apache.hadoop.fs.InvalidPathException;
3737
import org.apache.hadoop.fs.Path;
38+
import org.apache.hadoop.fs.PathIsNotEmptyDirectoryException;
3839
import org.apache.hadoop.fs.Trash;
3940
import org.apache.hadoop.fs.TrashPolicy;
4041
import org.apache.hadoop.fs.contract.ContractTestUtils;
@@ -362,6 +363,24 @@ public void testRecursiveDelete() throws Exception {
362363
ContractTestUtils.touch(fs, child);
363364
}
364365

366+
// delete a dir with sub-file
367+
try {
368+
FileStatus[] parents = fs.listStatus(grandparent);
369+
Assert.assertTrue(parents.length > 0);
370+
fs.delete(parents[0].getPath(), false);
371+
Assert.fail("Must throw exception as dir is not empty!");
372+
} catch (PathIsNotEmptyDirectoryException pde) {
373+
// expected
374+
}
375+
376+
// delete a dir with sub-file
377+
try {
378+
fs.delete(grandparent, false);
379+
Assert.fail("Must throw exception as dir is not empty!");
380+
} catch (PathIsNotEmptyDirectoryException pde) {
381+
// expected
382+
}
383+
365384
// Delete the grandparent, which should delete all keys.
366385
fs.delete(grandparent, true);
367386

@@ -770,7 +789,7 @@ public void testRenameToNewSubDirShouldNotExist() throws Exception {
770789

771790
// Add a sub-directory '/b/a' to '/b'. This is to verify that rename
772791
// throws exception as new destin /b/a already exists.
773-
final Path baPath = new Path(fs.getUri().toString() + "/b/a");
792+
final Path baPath = new Path(fs.getUri().toString() + "/b/a/c");
774793
fs.mkdirs(baPath);
775794

776795
Assert.assertFalse("New destin sub-path /b/a already exists",

0 commit comments

Comments
 (0)