-
Notifications
You must be signed in to change notification settings - Fork 616
HDDS-4040. [OFS] BasicRootedOzoneFileSystem to support batchDelete #1286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
171717f
fdbc71c
1eb6cde
fc8ae43
5865c2f
244a4be
5a13035
4b0a7d9
13a01ff
167240b
8d74023
e65e0d5
8a01be1
73d8223
5145690
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -27,6 +27,7 @@ | |||||||||||
| import java.util.Collections; | ||||||||||||
| import java.util.Iterator; | ||||||||||||
| import java.util.List; | ||||||||||||
| import java.util.stream.Collectors; | ||||||||||||
|
|
||||||||||||
| import com.google.common.base.Preconditions; | ||||||||||||
| import org.apache.commons.collections.CollectionUtils; | ||||||||||||
|
|
@@ -284,7 +285,7 @@ public void close() throws IOException { | |||||||||||
|
|
||||||||||||
| @Override | ||||||||||||
| public InputStream readFile(String pathStr) throws IOException { | ||||||||||||
| incrementCounter(Statistic.OBJECTS_READ); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_READ, 1); | ||||||||||||
| OFSPath ofsPath = new OFSPath(pathStr); | ||||||||||||
| String key = ofsPath.getKeyName(); | ||||||||||||
| try { | ||||||||||||
|
|
@@ -301,14 +302,19 @@ public InputStream readFile(String pathStr) throws IOException { | |||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| @Deprecated | ||||||||||||
| protected void incrementCounter(Statistic objectsRead) { | ||||||||||||
| //noop: Use OzoneClientAdapterImpl which supports statistics. | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have removed the old method from all Impls. Only kept it in |
||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| protected void incrementCounter(Statistic objectsRead, long count) { | ||||||||||||
| //noop: Use OzoneClientAdapterImpl which supports statistics. | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| @Override | ||||||||||||
| public OzoneFSOutputStream createFile(String pathStr, short replication, | ||||||||||||
| boolean overWrite, boolean recursive) throws IOException { | ||||||||||||
| incrementCounter(Statistic.OBJECTS_CREATED); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_CREATED, 1); | ||||||||||||
| OFSPath ofsPath = new OFSPath(pathStr); | ||||||||||||
| if (ofsPath.isRoot() || ofsPath.isVolume() || ofsPath.isBucket()) { | ||||||||||||
| throw new IOException("Cannot create file under root or volume."); | ||||||||||||
|
|
@@ -358,7 +364,7 @@ public void renameKey(String key, String newKeyName) throws IOException { | |||||||||||
| */ | ||||||||||||
| @Override | ||||||||||||
| public void rename(String path, String newPath) throws IOException { | ||||||||||||
| incrementCounter(Statistic.OBJECTS_RENAMED); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_RENAMED, 1); | ||||||||||||
| OFSPath ofsPath = new OFSPath(path); | ||||||||||||
| OFSPath ofsNewPath = new OFSPath(newPath); | ||||||||||||
|
|
||||||||||||
|
|
@@ -384,7 +390,7 @@ public void rename(String path, String newPath) throws IOException { | |||||||||||
| */ | ||||||||||||
| void rename(OzoneBucket bucket, String path, String newPath) | ||||||||||||
| throws IOException { | ||||||||||||
| incrementCounter(Statistic.OBJECTS_RENAMED); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_RENAMED, 1); | ||||||||||||
| OFSPath ofsPath = new OFSPath(path); | ||||||||||||
| OFSPath ofsNewPath = new OFSPath(newPath); | ||||||||||||
| // No same-bucket policy check here since this call path is controlled | ||||||||||||
|
|
@@ -402,7 +408,7 @@ void rename(OzoneBucket bucket, String path, String newPath) | |||||||||||
| @Override | ||||||||||||
| public boolean createDirectory(String pathStr) throws IOException { | ||||||||||||
| LOG.trace("creating dir for path: {}", pathStr); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_CREATED); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_CREATED, 1); | ||||||||||||
| OFSPath ofsPath = new OFSPath(pathStr); | ||||||||||||
| if (ofsPath.getVolumeName().isEmpty()) { | ||||||||||||
| // Volume name unspecified, invalid param, return failure | ||||||||||||
|
|
@@ -441,7 +447,7 @@ public boolean createDirectory(String pathStr) throws IOException { | |||||||||||
| @Override | ||||||||||||
| public boolean deleteObject(String path) { | ||||||||||||
| LOG.trace("issuing delete for path to key: {}", path); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_DELETED); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_DELETED, 1); | ||||||||||||
| OFSPath ofsPath = new OFSPath(path); | ||||||||||||
| String keyName = ofsPath.getKeyName(); | ||||||||||||
| if (keyName.length() == 0) { | ||||||||||||
|
|
@@ -457,45 +463,83 @@ public boolean deleteObject(String path) { | |||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * Helper function to check if the list of key paths are in the same volume | ||||||||||||
| * and same bucket. | ||||||||||||
| */ | ||||||||||||
| private boolean areInSameBucket(List<String> keyNameList) { | ||||||||||||
| if (keyNameList.size() == 0) { | ||||||||||||
|
smengcl marked this conversation as resolved.
Outdated
|
||||||||||||
| return true; | ||||||||||||
| } | ||||||||||||
| String firstKeyPath = keyNameList.get(0); | ||||||||||||
| final String volAndBucket = new OFSPath(firstKeyPath).getNonKeyPath(); | ||||||||||||
| // If any key path's volume and bucket from the second element and on | ||||||||||||
| // in the list doesn't match the first element's, hasDifferentVolAndBucket | ||||||||||||
| // would be true | ||||||||||||
| boolean hasDifferentVolAndBucket = keyNameList.stream().skip(1) | ||||||||||||
| .anyMatch(p -> !(new OFSPath(p).getNonKeyPath().equals(volAndBucket))); | ||||||||||||
| return !hasDifferentVolAndBucket; | ||||||||||||
|
smengcl marked this conversation as resolved.
Outdated
|
||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * Helper method to delete an object specified by key name in bucket. | ||||||||||||
| * | ||||||||||||
| * @param pathList key name list to be deleted | ||||||||||||
| * @return true if the key is deleted, false otherwise | ||||||||||||
| * Only supports deleting keys in the same bucket in one call. | ||||||||||||
| * | ||||||||||||
| * Each item in the given list should be the String of an OFS path: | ||||||||||||
| * e.g. ofs://om/vol1/buck1/k1 | ||||||||||||
| * | ||||||||||||
| * @param keyNameList key name list to be deleted | ||||||||||||
| * @return true if the key deletion is successful, false otherwise | ||||||||||||
| */ | ||||||||||||
| @Override | ||||||||||||
| public boolean deleteObjects(List<String> pathList) { | ||||||||||||
| // TODO: we will support deleteObjects in ofs. | ||||||||||||
| LOG.error("ofs currently does not support deleteObjects"); | ||||||||||||
| return false; | ||||||||||||
| public boolean deleteObjects(List<String> keyNameList) { | ||||||||||||
| if (keyNameList.size() == 0) { | ||||||||||||
|
smengcl marked this conversation as resolved.
|
||||||||||||
| return true; | ||||||||||||
| } | ||||||||||||
| // Sanity check. Support only deleting a list of keys in the same bucket | ||||||||||||
| if (!areInSameBucket(keyNameList)) { | ||||||||||||
| LOG.error("Deleting keys from different buckets in a single batch " | ||||||||||||
| + "is not supported."); | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
| try { | ||||||||||||
| OFSPath firstKeyPath = new OFSPath(keyNameList.get(0)); | ||||||||||||
| OzoneBucket bucket = getBucket(firstKeyPath, false); | ||||||||||||
| return deleteObjects(bucket, keyNameList); | ||||||||||||
| } catch (IOException ioe) { | ||||||||||||
| LOG.error("delete key failed: {}", ioe.getMessage()); | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /** | ||||||||||||
| * Package-private helper function to reduce calls to getBucket(). | ||||||||||||
| * | ||||||||||||
| * This will be faster than the public variant of the method since this | ||||||||||||
| * doesn't verify the same-bucket condition. | ||||||||||||
| * | ||||||||||||
| * @param bucket Bucket to operate in. | ||||||||||||
| * @param path Path to delete. | ||||||||||||
| * @return true if operation succeeded, false upon IOException. | ||||||||||||
| * @param keyNameList key name list to be deleted. | ||||||||||||
| * @return true if operation succeeded, false on IOException. | ||||||||||||
| */ | ||||||||||||
| boolean deleteObject(OzoneBucket bucket, String path) { | ||||||||||||
| LOG.trace("issuing delete for path to key: {}", path); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_DELETED); | ||||||||||||
| OFSPath ofsPath = new OFSPath(path); | ||||||||||||
| String keyName = ofsPath.getKeyName(); | ||||||||||||
| if (keyName.length() == 0) { | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
| boolean deleteObjects(OzoneBucket bucket, List<String> keyNameList) { | ||||||||||||
| List<String> keyList = keyNameList.stream() | ||||||||||||
| .map(p -> new OFSPath(p).getKeyName()) | ||||||||||||
| .collect(Collectors.toList()); | ||||||||||||
| try { | ||||||||||||
| bucket.deleteKey(keyName); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_DELETED, keyNameList.size()); | ||||||||||||
| bucket.deleteKeys(keyList); | ||||||||||||
| return true; | ||||||||||||
| } catch (IOException ioe) { | ||||||||||||
| LOG.error("delete key failed " + ioe.getMessage()); | ||||||||||||
| LOG.error("delete key failed: {}", ioe.getMessage()); | ||||||||||||
| return false; | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| public FileStatusAdapter getFileStatus(String path, URI uri, | ||||||||||||
| Path qualifiedPath, String userName) throws IOException { | ||||||||||||
| incrementCounter(Statistic.OBJECTS_QUERY); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_QUERY, 1); | ||||||||||||
| OFSPath ofsPath = new OFSPath(path); | ||||||||||||
| String key = ofsPath.getKeyName(); | ||||||||||||
| if (ofsPath.isRoot()) { | ||||||||||||
|
|
@@ -579,7 +623,7 @@ public Collection<FileStatus> getTrashRoots(boolean allUsers, | |||||||||||
|
|
||||||||||||
| @Override | ||||||||||||
| public Iterator<BasicKeyInfo> listKeys(String pathStr) { | ||||||||||||
| incrementCounter(Statistic.OBJECTS_LIST); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_LIST, 1); | ||||||||||||
| OFSPath ofsPath = new OFSPath(pathStr); | ||||||||||||
| String key = ofsPath.getKeyName(); | ||||||||||||
| OzoneBucket bucket; | ||||||||||||
|
|
@@ -668,7 +712,7 @@ public List<FileStatusAdapter> listStatus(String pathStr, boolean recursive, | |||||||||||
| String startPath, long numEntries, URI uri, | ||||||||||||
| Path workingDir, String username) throws IOException { | ||||||||||||
|
|
||||||||||||
| incrementCounter(Statistic.OBJECTS_LIST); | ||||||||||||
| incrementCounter(Statistic.OBJECTS_LIST, 1); | ||||||||||||
| // Remove authority from startPath if it exists | ||||||||||||
| if (startPath.startsWith(uri.toString())) { | ||||||||||||
| try { | ||||||||||||
|
|
||||||||||||
Uh oh!
There was an error while loading. Please reload this page.