-
Notifications
You must be signed in to change notification settings - Fork 451
Use a BufReader in bdk_file_store #1293
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| use bincode::Options; | ||
| use std::{ | ||
| fs::File, | ||
| io::{self, Seek}, | ||
| io::{self, BufReader, Seek}, | ||
| marker::PhantomData, | ||
| }; | ||
|
|
||
|
|
@@ -14,8 +14,9 @@ use crate::bincode_options; | |
| /// | ||
| /// [`next`]: Self::next | ||
| pub struct EntryIter<'t, T> { | ||
| db_file: Option<&'t mut File>, | ||
|
|
||
| /// Buffered reader around the file | ||
| db_file: BufReader<&'t mut File>, | ||
| finished: bool, | ||
| /// The file position for the first read of `db_file`. | ||
| start_pos: Option<u64>, | ||
| types: PhantomData<T>, | ||
|
|
@@ -24,8 +25,9 @@ pub struct EntryIter<'t, T> { | |
| impl<'t, T> EntryIter<'t, T> { | ||
| pub fn new(start_pos: u64, db_file: &'t mut File) -> Self { | ||
| Self { | ||
| db_file: Some(db_file), | ||
| db_file: BufReader::new(db_file), | ||
| start_pos: Some(start_pos), | ||
| finished: false, | ||
| types: PhantomData, | ||
| } | ||
| } | ||
|
|
@@ -38,44 +40,34 @@ where | |
| type Item = Result<T, IterError>; | ||
|
|
||
| fn next(&mut self) -> Option<Self::Item> { | ||
| // closure which reads a single entry starting from `self.pos` | ||
| let read_one = |f: &mut File, start_pos: Option<u64>| -> Result<Option<T>, IterError> { | ||
| let pos = match start_pos { | ||
| Some(pos) => f.seek(io::SeekFrom::Start(pos))?, | ||
| None => f.stream_position()?, | ||
| }; | ||
| if self.finished { | ||
| return None; | ||
| } | ||
| (|| { | ||
| if let Some(start) = self.start_pos.take() { | ||
| self.db_file.seek(io::SeekFrom::Start(start))?; | ||
| } | ||
|
|
||
| match bincode_options().deserialize_from(&*f) { | ||
| Ok(changeset) => { | ||
| f.stream_position()?; | ||
| Ok(Some(changeset)) | ||
| } | ||
| let pos_before_read = self.db_file.stream_position()?; | ||
| match bincode_options().deserialize_from(&mut self.db_file) { | ||
| Ok(changeset) => Ok(Some(changeset)), | ||
| Err(e) => { | ||
| self.finished = true; | ||
| let pos_after_read = self.db_file.stream_position()?; | ||
| // allow unexpected EOF if 0 bytes were read | ||
| if let bincode::ErrorKind::Io(inner) = &*e { | ||
| if inner.kind() == io::ErrorKind::UnexpectedEof { | ||
| let eof = f.seek(io::SeekFrom::End(0))?; | ||
| if pos == eof { | ||
| return Ok(None); | ||
| } | ||
| if inner.kind() == io::ErrorKind::UnexpectedEof | ||
| && pos_after_read == pos_before_read | ||
| { | ||
| return Ok(None); | ||
| } | ||
| } | ||
| f.seek(io::SeekFrom::Start(pos))?; | ||
| self.db_file.seek(io::SeekFrom::Start(pos_before_read))?; | ||
| Err(IterError::Bincode(*e)) | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| let result = read_one(self.db_file.as_mut()?, self.start_pos.take()); | ||
| if result.is_err() { | ||
| self.db_file = None; | ||
| } | ||
| result.transpose() | ||
| } | ||
| } | ||
|
|
||
| impl From<io::Error> for IterError { | ||
| fn from(value: io::Error) -> Self { | ||
| IterError::Io(value) | ||
| })() | ||
| .transpose() | ||
| } | ||
| } | ||
|
Comment on lines
67
to
72
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we still need a
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we write a test that demonstrates this need? I think I understand the rationale I'll see if I can come up one. [EDIT] or maybe we can use a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @LLFourn I don't think using a BufReader with the internal file getting written to is a good idea. We'll need to do some crazy stuff with I thought that the test I added demonstrated the need for the |
||
|
|
||
|
|
@@ -97,4 +89,10 @@ impl core::fmt::Display for IterError { | |
| } | ||
| } | ||
|
|
||
| impl From<io::Error> for IterError { | ||
| fn from(value: io::Error) -> Self { | ||
| IterError::Io(value) | ||
| } | ||
| } | ||
|
|
||
| impl std::error::Error for IterError {} | ||
Uh oh!
There was an error while loading. Please reload this page.