-
Notifications
You must be signed in to change notification settings - Fork 3.4k
AWS: Add check to create staging directory if not exists for S3OutputStream #3175
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 3 commits
30f52b1
05de05e
0ef2b28
523b701
cca5080
4cb6a0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,7 @@ | |
|
|
||
| import java.io.IOException; | ||
| import java.io.UncheckedIOException; | ||
| import java.security.AccessControlException; | ||
| import org.apache.iceberg.aws.AwsProperties; | ||
| import org.apache.iceberg.exceptions.AlreadyExistsException; | ||
| import org.apache.iceberg.io.InputFile; | ||
|
|
@@ -62,6 +63,9 @@ public PositionOutputStream createOrOverwrite() { | |
| return new S3OutputStream(client(), uri(), awsProperties()); | ||
| } catch (IOException e) { | ||
| throw new UncheckedIOException("Failed to create output stream for location: " + uri(), e); | ||
| } catch (SecurityException e) { | ||
|
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. as discussed in the block below, we can remove this catch. AccessControlException also hides the original exception, so better to not use it.
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. Removed the special handling for |
||
| throw new AccessControlException( | ||
| "Access denied while creating staging directory for output stream: " + uri()); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -86,7 +86,8 @@ class S3OutputStream extends PositionOutputStream { | |
| private boolean closed = false; | ||
|
|
||
| @SuppressWarnings("StaticAssignmentInConstructor") | ||
| S3OutputStream(S3Client s3, S3URI location, AwsProperties awsProperties) throws IOException { | ||
| S3OutputStream(S3Client s3, S3URI location, AwsProperties awsProperties) | ||
| throws IOException, SecurityException { | ||
|
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. same comment as below, remove SecurityException after throws
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. Removed it. |
||
| if (executorService == null) { | ||
| synchronized (S3OutputStream.class) { | ||
| if (executorService == null) { | ||
|
|
@@ -170,11 +171,12 @@ public void write(byte[] b, int off, int len) throws IOException { | |
| } | ||
| } | ||
|
|
||
| private void newStream() throws IOException { | ||
| private void newStream() throws IOException, SecurityException { | ||
|
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. Sorry for the back and forth, I read the documentation for mkdirs, it seems like SecurityException only catches JVM level permission and it might still just return false for OS level permission failure, so it's hard to have a consistent behavior for error handling. Because of that, plus the fact that SecurityException is a runtime exception, I think we can remove the special handling of it and just let it throw to the top level.
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. Removed the special handling for
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. Thanks, can you also remove the
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. Yeah, need not to throw explicitly. Removed it. |
||
| if (stream != null) { | ||
| stream.close(); | ||
| } | ||
|
|
||
| createStagingDirectoryIfNotExists(); | ||
| currentStagingFile = File.createTempFile("s3fileio-", ".tmp", stagingDirectory); | ||
| currentStagingFile.deleteOnExit(); | ||
| stagingFiles.add(currentStagingFile); | ||
|
|
@@ -328,6 +330,15 @@ private static InputStream uncheckedInputStream(File file) { | |
| } | ||
| } | ||
|
|
||
| private void createStagingDirectoryIfNotExists() throws SecurityException { | ||
| if (!stagingDirectory.exists()) { | ||
|
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. add a LOG saying something like "staging directoy {} not exist, trying to create one"
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. Added the logger. |
||
| boolean createdStagingDirectory = stagingDirectory.mkdirs(); | ||
| if (createdStagingDirectory) { | ||
| LOG.info("Successfully created staging directory: {}", stagingDirectory.getAbsolutePath()); | ||
| } | ||
|
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. else, add a LOG saying "Staging directory {} creation failed, or it is created by another process"
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. actually, we can do better than just logging. When creation fails, we can check directory existence again, if it exists then it's created by another process, otherwise it's still an issue, and we can throw an IOException with error message indicating staging directory creation fails for some unknown reasons.
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. Agreed, I have made the changes accordingly. |
||
| } | ||
| } | ||
|
|
||
| @SuppressWarnings("checkstyle:NoFinalizer") | ||
| @Override | ||
| protected void finalize() throws Throwable { | ||
|
|
||
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.
as discussed in the block below, we can just document @throws SecurityException if staging directory creation fails due to missing JVM level permission.
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.
I have made the changes accordingly.