HDDS-14370. RandomAccessFileChannel to implement Closeable#9628
HDDS-14370. RandomAccessFileChannel to implement Closeable#9628rich7420 wants to merge 3 commits intoapache:masterfrom
Conversation
Gargi-jais11
left a comment
There was a problem hiding this comment.
Thanks @rich7420 for the patch.
Please see the inline comment.
| @Override | ||
| public synchronized void close() { | ||
| if (blockFile == null) { | ||
| return; | ||
| } | ||
| blockFile = null; | ||
| try { |
There was a problem hiding this comment.
This is not related to your changes but I found a bug over here.
Here, blockFile is set to null before it was used in the catch blocks
for error logging. This would cause log messages to show null instead of the actual file path when closing fails making debugging difficult.
Solution: Save the file reference so that error messages can properly display the file path.
public synchronized void close() {
if (blockFile == null) {
return;
}
final File fileToClose = blockFile;
blockFile = null;
try {
channel.close();
channel = null;
} catch (IOException e) {
LOG.warn("Failed to close channel for {}", fileToClose, e);
}
try {
raf.close();
raf = null;
} catch (IOException e) {
LOG.warn("Failed to close RandomAccessFile for {}", fileToClose, e);
}
}
}
jojochuang
left a comment
There was a problem hiding this comment.
Better to have a test file for this class: TestRandomAccessFileChannel
|
Below the few test cases suggestion which I could think as of now:
It would be great @rich7420 if you come up with some more critical tests. |
|
got it! thanks for the review @jojochuang , @Gargi-jais11 ! |
Gargi-jais11
left a comment
There was a problem hiding this comment.
Please find the inline comments
| final File fileToClose = blockFile; | ||
| if (fileToClose == null) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Check for null before copying blockFile.
| final File fileToClose = blockFile; | |
| if (fileToClose == null) { | |
| return; | |
| } | |
| if (blockFile == null) { | |
| return; // Already closed | |
| } | |
| // Store file reference for logging before clearing | |
| final File fileToClose = blockFile; | |
| blockFile = null; | |
| } |
| public synchronized void open(File file) throws FileNotFoundException { | ||
| Preconditions.assertNull(blockFile, "blockFile"); | ||
| blockFile = Objects.requireNonNull(file, "blockFile == null"); | ||
| raf = new RandomAccessFile(blockFile, "r"); | ||
| channel = raf.getChannel(); | ||
| final File f = Objects.requireNonNull(file, "blockFile == null"); | ||
| final RandomAccessFile newRaf = new RandomAccessFile(f, "r"); | ||
| final FileChannel newChannel = newRaf.getChannel(); | ||
| blockFile = f; | ||
| raf = newRaf; | ||
| channel = newChannel; | ||
| } |
There was a problem hiding this comment.
I think we should consider wrapping open() in try-catch to clean up on failure .
I am saying this as I suggest that :
If FileNotFoundException is thrown: blockFile is set, but raf and channel remain null.
Here the problem is that isOpen() returns true (because blockFile != null), but the object isn't usable. And will the subsequent calls to read() or position() will fail with NPE when accessing channel
What changes were proposed in this pull request?
The class already had a close() method but didn't implement Closeable, which could lead to resource leaks if developers miss calling close().
What is the link to the Apache JIRA
HDDS-14370
How was this patch tested?
https://github.com/rich7420/ozone/actions/runs/20941407661