-
Notifications
You must be signed in to change notification settings - Fork 53
Fix #329: Empty RAF creation on read #330
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
Conversation
handle.read(); // this will fail as there is no underlying file! | ||
fail("Read successfully from non-existing file!"); | ||
} | ||
catch (final Exception exc) { |
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.
How about catching only IOException
instead of Exception
here?
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, I just pushed an updated version that does just that.
e868c41
to
ceb430f
Compare
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 is awesome! Splitting the RAF logic along read/write lines is exactly the right change to finally fix this bugbear. I have only a few minor comments+nitpicks, and then we should be good to merge.
assertFalse(nonExistentFile.exists()); | ||
|
||
final FileLocation loc = new FileLocation(uri); | ||
final DataHandle<?> handle = dhs.create(loc); |
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.
We should use try-with-resources here, no?
try (final DataHandle<?> handle = dhs.create(loc)) {
...
}
So that it definitely gets closed at the end, regardless of the outcome of the test
} | ||
|
||
@Override | ||
public long length() throws IOException { | ||
return exists() ? raf().length() : -1; | ||
return exists() ? writeRaf().length() : -1; |
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.
Conceptually, this should be readRaf()
since querying the length is a "read" operation. (I realize that in practice, it won't matter due to the exists()
check beforehand, but the code looks strange/wrong with writeRaf()
here.)
*/ | ||
private RandomAccessFile readRaf() throws IOException { | ||
if (raf == null) { | ||
if (!exists()) { |
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 would prefer this exists()
check live in the initRAF()
method. It can be done by making the method initRAF(final boolean create)
and then writing if (!create && !exists()) throw ...
. Then, here in readRAF()
, simply put if (raf == null) initRAF(false);
—and correspondingly, initRAF(true)
in the writeRAF()
method. Then the two methods will be symmetrical, and IMHO easier to understand.
Note also the case of RAF
—it is an acronym, so should be all capitals, not camel case Raf
. Maybe we want to call them reader()
and writer()
instead of readRaf()
and writeRaf()
? I feel like readRaf()
and writeRaf()
are somehow too long/unwieldy.
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.
Great suggestion, this makes the code much cleaner :)
ceb430f
to
83fd2a1
Compare
Thanks for the input @ctrueden I integrated your comments and it should be good to go now. |
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.
Just a handful of little things now!
@@ -101,199 +101,199 @@ public Date lastModified() { | |||
|
|||
@Override | |||
public long offset() throws IOException { | |||
return raf().getFilePointer(); | |||
return exists() ? writer().getFilePointer() : 0; |
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 should be reader()
.
@@ -62,7 +62,7 @@ | |||
|
|||
/** Gets the random access file object backing this FileHandle. */ | |||
public RandomAccessFile getRandomAccessFile() throws IOException { | |||
return raf(); | |||
return writer(); |
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.
We should amend the javadoc of this method to indicate that calling this method will create the file if it does not already exist.
* independently of the underlying file existing on disk. This allows us to | ||
* create a new file for writing. | ||
* | ||
* @return the internal {@link RandomAccessFile} or creates if if 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.
Should be the internal {@link RandomAccessFile}, creating it if needed.
* if the underlying file exists on disk. This prevents accidental creation of | ||
* an empty RAF file when calling read operations on a non-existent file. | ||
* | ||
* @return the internal {@link RandomAccessFile} or creates if if 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.
Should be the internal {@link RandomAccessFile}, creating it if needed.
} | ||
|
||
/** | ||
* Initializes the {@link RandomAccessFile}, |
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.
,
➡️ .
* @param create whether to create the {@link RandomAccessFile} if the | ||
* underlying file does not exist yet. | ||
* @throws IOException if the {@link RandomAccessFile} could not be created, | ||
* or the backing file does not exists and the {@code create} |
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.
exists
➡️ exist
* underlying file does not exist yet. | ||
* @throws IOException if the {@link RandomAccessFile} could not be created, | ||
* or the backing file does not exists and the {@code create} | ||
* parameter was set to {@code true}. |
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.
true
➡️ false
When trying to read from a non-existing file, the FileHandle created a RandomAccessFile, which resulted in an empty file appearing on disk.
83fd2a1
to
15b70a1
Compare
|
Thanks @gab1one !! |
When trying to read from a non-existing file, the FileHandle creates a RandomAccessFile, which results in an empty file appearing on disk. This PR fixes this by throwing an IOException when trying to read from a non-existent file.