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
KAFKA-4902: Utils#delete should correctly handle I/O errors and symlinks #2691
Conversation
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
retest this please |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
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.
@cmccabe : Thanks for the patch. Looks good to me. Just a couple of minor comments.
try { | ||
segment.destroy(); | ||
} catch (IOException e) { | ||
log.error("Error destroying segment id {}", segment.id, e); |
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.
Probably include both segment.id and and segment.name()?
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.
Seems like it would be better to add a toString
to the segment or superclass.
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.
Good point. It looks like RocksDBStore
already has a toString
method. So I will just rely on that.
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 did not find any toString
in RocksDBStore
so I added one in Segment
(which can then expose the id, which is not something that RocksDBStore
knows about).
TestUtils.tempDirectory(tempDir.toPath(), "b"); | ||
TestUtils.tempDirectory(tempDir2.toPath(), "c"); | ||
Utils.delete(tempDir); // deleting a directory hierarchy works | ||
Utils.delete(tempDir); // deleting a non-existent directory hierarchy works |
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.
In this test, should we verify that the file/directory is actually gone after deletion?
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 agree with jun, makes sense to test that the removal succeeded.
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.
added
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.
Thanks for the PR, left a couple of minor comments. Great to use the better API to delete files recursively. I have been meaning to do that for a while. :)
try { | ||
segment.destroy(); | ||
} catch (IOException e) { | ||
log.error("Error destroying segment id {}", segment.id, e); |
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.
Seems like it would be better to add a toString
to the segment or superclass.
Utils.delete(stateDir); | ||
} | ||
public void cleanup() throws IOException { | ||
Utils.delete(stateDir); |
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.
Have you verified that the exists
was not there for a reason? Otherwise we may get failures during cleanup, which may obscure the real issue?
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.
This exists
is not necessary because Utils#delete
does not fail when given a non-existent path. (It had this behavior earlier as well, this patch didn't change it.)
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
retest this please |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Can you please rebase/merge from trunk so that the checkstyle issue that is preventing the PR builds from passing is fixed? |
retest this please |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
Refer to this link for build results (access rights to CI server needed): |
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.
LGTM, merging to trunk after a couple of minor tweaks: added Segment.toString
and tweaked a few assertions.
@@ -568,19 +572,30 @@ public static ByteBuffer ensureCapacity(ByteBuffer existingBuffer, int newLength | |||
* | |||
* @param file The root file at which to begin deleting | |||
*/ | |||
public static void delete(File file) { | |||
if (file == null) { | |||
public static void delete(final File file) throws IOException { |
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.
Maybe we should rename this to deleteIfExists
since we don't throw an error if file
doesn't exist. Probably in a subsequent PR if that makes sense to you.
|
||
// Test that deleting a non-existent directory hierarchy works. | ||
Utils.delete(tempDir); | ||
assertFalse(Files.isDirectory(tempDir.toPath())); |
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 changed all the isDirectory
checks to exists
. Both work, but I think the latter is a bit more explicit about what we're checking.
No description provided.