Skip to content

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

Merged
merged 2 commits into from
Jun 21, 2018
Merged

Fix #329: Empty RAF creation on read #330

merged 2 commits into from
Jun 21, 2018

Conversation

gab1one
Copy link
Contributor

@gab1one gab1one commented Jun 19, 2018

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.

@gab1one gab1one requested a review from ctrueden June 19, 2018 10:28
handle.read(); // this will fail as there is no underlying file!
fail("Read successfully from non-existing file!");
}
catch (final Exception exc) {
Copy link
Member

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?

Copy link
Contributor Author

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.

@gab1one gab1one force-pushed the fix-raf-creation branch from e868c41 to ceb430f Compare June 19, 2018 13:08
Copy link
Member

@ctrueden ctrueden left a 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);
Copy link
Member

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;
Copy link
Member

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()) {
Copy link
Member

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.

Copy link
Contributor Author

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 :)

@gab1one gab1one force-pushed the fix-raf-creation branch from ceb430f to 83fd2a1 Compare June 20, 2018 12:06
@gab1one
Copy link
Contributor Author

gab1one commented Jun 20, 2018

Thanks for the input @ctrueden I integrated your comments and it should be good to go now.

Copy link
Member

@ctrueden ctrueden left a 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;
Copy link
Member

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();
Copy link
Member

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.
Copy link
Member

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.
Copy link
Member

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},
Copy link
Member

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}
Copy link
Member

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}.
Copy link
Member

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.
@gab1one gab1one force-pushed the fix-raf-creation branch from 83fd2a1 to 15b70a1 Compare June 20, 2018 16:19
@gab1one
Copy link
Contributor Author

gab1one commented Jun 21, 2018

Just a handful of little things now!
Also included :)

@ctrueden ctrueden merged commit 560ad96 into master Jun 21, 2018
@ctrueden
Copy link
Member

Thanks @gab1one !!

@ctrueden ctrueden deleted the fix-raf-creation branch June 21, 2018 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants