Skip to content

Commit 4295d4e

Browse files
committed
HDDS-4358: Delete : make delete an atomic operation (#1607)
1 parent 623da7b commit 4295d4e

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
@@ -291,9 +291,12 @@ OzoneInputStream getKey(String volumeName, String bucketName, String keyName)
291291
* @param volumeName Name of the Volume
292292
* @param bucketName Name of the Bucket
293293
* @param keyName Name of the Key
294+
* @param recursive recursive deletion of all sub path keys if true,
295+
* otherwise non-recursive
294296
* @throws IOException
295297
*/
296-
void deleteKey(String volumeName, String bucketName, String keyName)
298+
void deleteKey(String volumeName, String bucketName, String keyName,
299+
boolean recursive)
297300
throws IOException;
298301

299302
/**

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
@@ -757,7 +757,7 @@ public OzoneInputStream getKey(
757757

758758
@Override
759759
public void deleteKey(
760-
String volumeName, String bucketName, String keyName)
760+
String volumeName, String bucketName, String keyName, boolean recursive)
761761
throws IOException {
762762
verifyVolumeName(volumeName);
763763
verifyBucketName(bucketName);
@@ -766,6 +766,7 @@ public void deleteKey(
766766
.setVolumeName(volumeName)
767767
.setBucketName(bucketName)
768768
.setKeyName(keyName)
769+
.setRecursive(recursive)
769770
.build();
770771
ozoneManagerClient.deleteKey(keyArgs);
771772
}

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
@@ -746,7 +746,8 @@ public void deleteKey(OmKeyArgs args) throws IOException {
746746
KeyArgs keyArgs = KeyArgs.newBuilder()
747747
.setVolumeName(args.getVolumeName())
748748
.setBucketName(args.getBucketName())
749-
.setKeyName(args.getKeyName()).build();
749+
.setKeyName(args.getKeyName())
750+
.setRecursive(args.isRecursive()).build();
750751
req.setKeyArgs(keyArgs);
751752

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

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

@@ -786,7 +805,7 @@ public void testRenameToNewSubDirShouldNotExist() throws Exception {
786805

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

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

0 commit comments

Comments
 (0)