-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Support integrating TOS as the UnderFileSystem #18621
Merged
Merged
Changes from 5 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
8c53b8b
tosv0.1
thu-david 044ae5a
update v0.2
thu-david a8b0124
fix NPE for getListing
Jackson-Wang-7 209f284
fix NPE for getListing
Jackson-Wang-7 38a4f11
fix mkdir issue
Jackson-Wang-7 e260beb
fix some bugs
thu-david 2d657e7
Update AlluxioTosException.java
thu-david a15f9f6
remove some logs
thu-david b4a8a73
fix
thu-david File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<!-- | ||
|
||
The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 | ||
(the "License"). You may not use this work except in compliance with the License, which is | ||
available at www.apache.org/licenses/LICENSE-2.0 | ||
|
||
This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | ||
either express or implied, as more fully set forth in the License. | ||
|
||
See the NOTICE file distributed with this work for information regarding copyright ownership. | ||
|
||
--> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<parent> | ||
<groupId>org.alluxio</groupId> | ||
<artifactId>alluxio-underfs</artifactId> | ||
<version>2.10.0-SNAPSHOT</version> | ||
</parent> | ||
<artifactId>alluxio-underfs-tos</artifactId> | ||
<name>Alluxio Under File System - Tinder Object Storage</name> | ||
<description>Tinder Object Storage Under File System implementation</description> | ||
|
||
<properties> | ||
<!-- The following paths need to be defined here as well as in the parent pom so that mvn can --> | ||
<!-- run properly from sub-project directories --> | ||
<build.path>${project.parent.parent.basedir}/build</build.path> | ||
</properties> | ||
|
||
<dependencies> | ||
<!-- External dependencies --> | ||
<dependency> | ||
<groupId>com.volcengine</groupId> | ||
<artifactId>ve-tos-java-sdk</artifactId> | ||
<version>2.7.1</version> | ||
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. define the version in the root pom.xml, not here |
||
</dependency> | ||
<dependency> | ||
<groupId>commons-codec</groupId> | ||
<artifactId>commons-codec</artifactId> | ||
</dependency> | ||
|
||
<!-- Internal dependencies --> | ||
<dependency> | ||
<groupId>org.alluxio</groupId> | ||
<artifactId>alluxio-core-common</artifactId> | ||
<version>${project.version}</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
|
||
<!-- Internal test dependencies --> | ||
<dependency> | ||
<groupId>org.alluxio</groupId> | ||
<artifactId>alluxio-core-common</artifactId> | ||
<version>${project.version}</version> | ||
<type>test-jar</type> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-inline</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-shade-plugin</artifactId> | ||
</plugin> | ||
<plugin> | ||
<groupId>com.coderplus.maven.plugins</groupId> | ||
<artifactId>copy-rename-maven-plugin</artifactId> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
101 changes: 101 additions & 0 deletions
101
underfs/tos/src/main/java/alluxio/underfs/tos/AlluxioTosException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 | ||
* (the "License"). You may not use this work except in compliance with the License, which is | ||
* available at www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | ||
* either express or implied, as more fully set forth in the License. | ||
* | ||
* See the NOTICE file distributed with this work for information regarding copyright ownership. | ||
*/ | ||
|
||
package alluxio.underfs.tos; | ||
|
||
import alluxio.exception.runtime.AlluxioRuntimeException; | ||
import alluxio.grpc.ErrorType; | ||
|
||
import com.volcengine.tos.TosException; | ||
import io.grpc.Status; | ||
|
||
import java.net.HttpURLConnection; | ||
|
||
/** | ||
* Alluxio exception for cos. | ||
*/ | ||
public class AlluxioTosException extends AlluxioRuntimeException { | ||
private static final ErrorType ERROR_TYPE = ErrorType.External; | ||
|
||
/** | ||
* Converts an TosClientException to a corresponding AlluxioTosException. | ||
* | ||
* @param cause tos exception | ||
* @return alluxio tos exception | ||
*/ | ||
public static AlluxioTosException from(TosException cause) { | ||
return from(null, cause); | ||
} | ||
|
||
/** | ||
* Converts an CosClientException with errormessage to a corresponding AlluxioCosException. | ||
* | ||
* @param errorMessage error message | ||
* @param cause cos exception | ||
* @return alluxio cos exception | ||
*/ | ||
public static AlluxioTosException from(String errorMessage, TosException cause) { | ||
Status status = Status.UNKNOWN; | ||
String errorDescription = "Exception:" + cause.getMessage(); | ||
if (cause instanceof TosException) { | ||
TosException exception = (TosException) cause; | ||
status = httpStatusToGrpcStatus(exception.getStatusCode()); | ||
errorDescription = exception.getCode() + ":" + exception.getMessage(); | ||
} | ||
if (errorMessage == null) { | ||
errorMessage = errorDescription; | ||
} | ||
return new AlluxioTosException(status, errorMessage, cause, true); | ||
} | ||
|
||
private AlluxioTosException(Status status, String message, Throwable cause, boolean isRetryAble) { | ||
super(status, message, cause, ERROR_TYPE, isRetryAble); | ||
} | ||
|
||
private static Status httpStatusToGrpcStatus(int httpStatusCode) { | ||
if (httpStatusCode >= 100 && httpStatusCode < 200) { | ||
// 1xx. These headers should have been ignored. | ||
return Status.INTERNAL; | ||
} | ||
switch (httpStatusCode) { | ||
case HttpURLConnection.HTTP_BAD_REQUEST: // 400 | ||
Jackson-Wang-7 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return Status.INVALID_ARGUMENT; | ||
case HttpURLConnection.HTTP_UNAUTHORIZED: // 401 | ||
return Status.UNAUTHENTICATED; | ||
case HttpURLConnection.HTTP_FORBIDDEN: // 403 | ||
return Status.PERMISSION_DENIED; | ||
case HttpURLConnection.HTTP_NOT_FOUND: // 404 | ||
return Status.NOT_FOUND; | ||
case HttpURLConnection.HTTP_BAD_METHOD: // 405 | ||
case HttpURLConnection.HTTP_NOT_IMPLEMENTED: // 501 | ||
return Status.UNIMPLEMENTED; | ||
case HttpURLConnection.HTTP_CONFLICT: // 409 | ||
return Status.ABORTED; | ||
case HttpURLConnection.HTTP_LENGTH_REQUIRED: // 411 | ||
case HttpURLConnection.HTTP_PRECON_FAILED: // 412 | ||
return Status.FAILED_PRECONDITION; | ||
case 416: // Requested Range Not Satisfiable | ||
return Status.OUT_OF_RANGE; | ||
case HttpURLConnection.HTTP_INTERNAL_ERROR: //500 | ||
return Status.INTERNAL; | ||
case HttpURLConnection.HTTP_MOVED_PERM: // 301 | ||
case HttpURLConnection.HTTP_NOT_MODIFIED: //304 | ||
case 307: // Moved Temporarily | ||
case HttpURLConnection.HTTP_BAD_GATEWAY: // 502 | ||
case HttpURLConnection.HTTP_UNAVAILABLE: // 503 | ||
return Status.UNAVAILABLE; | ||
case HttpURLConnection.HTTP_GATEWAY_TIMEOUT: // 504 | ||
return Status.DEADLINE_EXCEEDED; | ||
default: | ||
return Status.UNKNOWN; | ||
} | ||
} | ||
} |
131 changes: 131 additions & 0 deletions
131
underfs/tos/src/main/java/alluxio/underfs/tos/TOSInputStream.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,131 @@ | ||||||
/* | ||||||
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0 | ||||||
* (the "License"). You may not use this work except in compliance with the License, which is | ||||||
* available at www.apache.org/licenses/LICENSE-2.0 | ||||||
* | ||||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, | ||||||
* either express or implied, as more fully set forth in the License. | ||||||
* | ||||||
* See the NOTICE file distributed with this work for information regarding copyright ownership. | ||||||
*/ | ||||||
|
||||||
package alluxio.underfs.tos; | ||||||
|
||||||
import alluxio.retry.RetryPolicy; | ||||||
import alluxio.underfs.MultiRangeObjectInputStream; | ||||||
|
||||||
import com.volcengine.tos.TOSV2; | ||||||
import com.volcengine.tos.TosException; | ||||||
import com.volcengine.tos.model.object.GetObjectV2Input; | ||||||
import com.volcengine.tos.model.object.GetObjectV2Output; | ||||||
import com.volcengine.tos.model.object.HeadObjectV2Input; | ||||||
import com.volcengine.tos.model.object.HeadObjectV2Output; | ||||||
import com.volcengine.tos.model.object.ObjectMetaRequestOptions; | ||||||
import org.apache.http.HttpStatus; | ||||||
import org.slf4j.Logger; | ||||||
import org.slf4j.LoggerFactory; | ||||||
|
||||||
import java.io.BufferedInputStream; | ||||||
import java.io.IOException; | ||||||
import java.io.InputStream; | ||||||
import javax.annotation.concurrent.NotThreadSafe; | ||||||
|
||||||
/** | ||||||
* A stream for reading a file from COS. This input stream returns 0 when calling read with an empty | ||||||
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
|
||||||
* buffer. | ||||||
*/ | ||||||
@NotThreadSafe | ||||||
public class TOSInputStream extends MultiRangeObjectInputStream { | ||||||
private static final Logger LOG = LoggerFactory.getLogger(TOSInputStream.class); | ||||||
|
||||||
/** | ||||||
* Bucket name of the Alluxio TOS bucket. | ||||||
*/ | ||||||
private final String mBucketName; | ||||||
|
||||||
/** | ||||||
* Key of the file in TOS to read. | ||||||
*/ | ||||||
private final String mKey; | ||||||
|
||||||
/** | ||||||
* The TOS client for TOS operations. | ||||||
*/ | ||||||
private final TOSV2 mTosClient; | ||||||
|
||||||
/** | ||||||
* The size of the object in bytes. | ||||||
*/ | ||||||
private final long mContentLength; | ||||||
|
||||||
/** | ||||||
* Policy determining the retry behavior in case the key does not exist. The key may not exist | ||||||
* because of eventual consistency. | ||||||
*/ | ||||||
private final RetryPolicy mRetryPolicy; | ||||||
|
||||||
/** | ||||||
* Creates a new instance of {@link TOSInputStream}. | ||||||
* | ||||||
* @param bucketName the name of the bucket | ||||||
* @param key the key of the file | ||||||
* @param client the client for COS | ||||||
* @param multiRangeChunkSize the chunk size to use on this stream | ||||||
*/ | ||||||
TOSInputStream(String bucketName, String key, TOSV2 client, RetryPolicy retryPolicy, | ||||||
long multiRangeChunkSize) throws IOException { | ||||||
this(bucketName, key, client, 0L, retryPolicy, multiRangeChunkSize); | ||||||
} | ||||||
|
||||||
/** | ||||||
* Creates a new instance of {@link TOSInputStream}. | ||||||
* | ||||||
* @param bucketName the name of the bucket | ||||||
* @param key the key of the file | ||||||
* @param client the client for TOS | ||||||
* @param position the position to begin reading from | ||||||
* @param multiRangeChunkSize the chunk size to use on this stream | ||||||
*/ | ||||||
TOSInputStream(String bucketName, String key, TOSV2 client, long position, | ||||||
RetryPolicy retryPolicy, long multiRangeChunkSize) throws IOException { | ||||||
super(multiRangeChunkSize); | ||||||
mBucketName = bucketName; | ||||||
mKey = key; | ||||||
mTosClient = client; | ||||||
mPos = position; | ||||||
mRetryPolicy = retryPolicy; | ||||||
HeadObjectV2Input input = new HeadObjectV2Input().setBucket(bucketName).setKey(key); | ||||||
HeadObjectV2Output meta = mTosClient.headObject(input); | ||||||
mContentLength = meta == null ? 0 : meta.getContentLength(); | ||||||
} | ||||||
|
||||||
@Override | ||||||
protected InputStream createStream(long startPos, long endPos) | ||||||
throws IOException { | ||||||
ObjectMetaRequestOptions options = new ObjectMetaRequestOptions(); | ||||||
GetObjectV2Input req = new GetObjectV2Input().setBucket(mBucketName).setKey(mKey); | ||||||
// TOS returns entire object if we read past the end | ||||||
options.setRange(startPos, endPos < mContentLength ? endPos - 1 : mContentLength - 1); | ||||||
req.setOptions(options); | ||||||
TosException lastException = null; | ||||||
String errorMessage = String.format("Failed to open key: %s bucket: %s", mKey, mBucketName); | ||||||
RetryPolicy retryPolicy = mRetryPolicy.copy(); | ||||||
while (retryPolicy.attempt()) { | ||||||
try { | ||||||
GetObjectV2Output object = mTosClient.getObject(req); | ||||||
return new BufferedInputStream(object.getContent()); | ||||||
} catch (TosException e) { | ||||||
errorMessage = String | ||||||
.format("Failed to open key: %s bucket: %s attempts: %d error: %s", mKey, mBucketName, | ||||||
retryPolicy.getAttemptCount(), e.getMessage()); | ||||||
if (e.getStatusCode() != HttpStatus.SC_NOT_FOUND) { | ||||||
throw new IOException(errorMessage, e); | ||||||
} | ||||||
// Key does not exist | ||||||
lastException = e; | ||||||
} | ||||||
} | ||||||
// Failed after retrying key does not exist | ||||||
throw new IOException(errorMessage, lastException); | ||||||
} | ||||||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please align to the previous line.