Skip to content

Commit b9ceda9

Browse files
committed
HDDS-4358: Delete : make delete an atomic operation (#1607)
1 parent eedb46e commit b9ceda9

File tree

25 files changed

+749
-229
lines changed

25 files changed

+749
-229
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
@@ -744,7 +744,8 @@ public void deleteKey(OmKeyArgs args) throws IOException {
744744
KeyArgs keyArgs = KeyArgs.newBuilder()
745745
.setVolumeName(args.getVolumeName())
746746
.setBucketName(args.getBucketName())
747-
.setKeyName(args.getKeyName()).build();
747+
.setKeyName(args.getKeyName())
748+
.setRecursive(args.isRecursive()).build();
748749
req.setKeyArgs(keyArgs);
749750

750751
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;
@@ -377,6 +378,24 @@ public void testRecursiveDelete() throws Exception {
377378
ContractTestUtils.touch(fs, child);
378379
}
379380

381+
// delete a dir with sub-file
382+
try {
383+
FileStatus[] parents = fs.listStatus(grandparent);
384+
Assert.assertTrue(parents.length > 0);
385+
fs.delete(parents[0].getPath(), false);
386+
Assert.fail("Must throw exception as dir is not empty!");
387+
} catch (PathIsNotEmptyDirectoryException pde) {
388+
// expected
389+
}
390+
391+
// delete a dir with sub-file
392+
try {
393+
fs.delete(grandparent, false);
394+
Assert.fail("Must throw exception as dir is not empty!");
395+
} catch (PathIsNotEmptyDirectoryException pde) {
396+
// expected
397+
}
398+
380399
// Delete the grandparent, which should delete all keys.
381400
fs.delete(grandparent, true);
382401

@@ -785,7 +804,7 @@ public void testRenameToNewSubDirShouldNotExist() throws Exception {
785804

786805
// Add a sub-directory '/b/a' to '/b'. This is to verify that rename
787806
// throws exception as new destin /b/a already exists.
788-
final Path baPath = new Path(fs.getUri().toString() + "/b/a");
807+
final Path baPath = new Path(fs.getUri().toString() + "/b/a/c");
789808
fs.mkdirs(baPath);
790809

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

0 commit comments

Comments
 (0)