-
Notifications
You must be signed in to change notification settings - Fork 448
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
WIP - ActionKV Index Maintenance - maybe bug #11
WIP - ActionKV Index Maintenance - maybe bug #11
Conversation
Reproducing the doc comment in `get_at` here for posterity Even though `f.seek` does take `&mut self`, my understanding is calling it with `SeekFrom::Current(0)` simply says "where am I at in the stream" without altering anything. In fact there's even a convenience function that claims exactly this: https://doc.rust-lang.org/std/io/trait.Seek.html#method.stream_position However, commenting these two lines makes `test_index_maintenance` pass
The method no longer assumes the storage file is already pointing at the end of the file. Previously, this bug was covered up small storage sizes by the BufReader used in `get`. When the entire file is smaller than the buffer, any read to the file will result in the file's seek position pointing to the end of the file. My debug print statement revealed the bug because calling BufReader.seek(SeekFrom::Current(0)) was resetting the file position to the same location it would have been without the buffer.
So the answer is that In that case, any read results in My debug print statement "revealed" the bug because it sets the seek position back to it's "natural" position. If you'd like to verify this yourself, run the test as in 8fb3d55, and then alter the See: https://doc.rust-lang.org/src/std/io/buffered.rs.html#374-379 if let SeekFrom::Current(n) = pos {
let remainder = (self.cap - self.pos) as i64;
// it should be safe to assume that remainder fits within an i64 as the alternative
// means we managed to allocate 8 exbibytes and that's absurd.
// But it's not out of the realm of possibility for some weird underlying reader to
// support seeking by i64::min_value() so we need to handle underflow when subtracting
// remainder.
if let Some(offset) = n.checked_sub(remainder) {
result = self.inner.seek(SeekFrom::Current(offset))?;
} else {
// seek backwards by our remainder, and then by the offset
self.inner.seek(SeekFrom::Current(-remainder))?;
self.discard_buffer();
result = self.inner.seek(SeekFrom::Current(n))?;
} |
Thank you very much for looking into this @Michael-J-Ward. |
I'll mark this PR as merged as I update my manuscript (which is held in a private repo on Manning's infrastructure). |
Thanks again for the input @Michael-J-Ward. |
Hey - want to start out by saying thank again for the great book!
The
insert_but_ignore_index
code appears incorrect to me. If the underlying file is pointing at positionin_the_middle
wheninsert
is called, the KV will be correctly appended at the end of the file, but theindex
will say the KV is at positionin_the_middle
code/ch7/ch7-actionkv2/src/lib.rs
Lines 174 to 182 in e23c70e
I wrote
test_index_maintenance
to confirm my suspicion, expecting it to fail. But the test passes!To understand what was happening, I altered
get_at
to print out the file' position after performing the read - and then the test fails!So now there's at least these few options on what's going on.
.seek(SeekFrom::Current(0))
is not actually a functional no-op, and calling it breaks the system in some expected way. i.e. what I thought looked like a bug in.insert
isn't a bug..insert
and for some magic the.seek(SeekFrom::Current(0))
sheds light on it. (Maybe something due to the extra buffer flush?.seek(SeekFrom::Current(0))
is intended to be a no-op, but there is a bug in it that this case triggered.I'd assume
1
is by far the most likely, followed by2
and then3
a long way off.Either way hope this helps and interested to hear what the answer is!
(Related: #4 since it also mentions the in memory index)