Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Fix Snapshot restoration failure on Windows #9491

Merged
merged 4 commits into from
Sep 10, 2018
Merged

Fix Snapshot restoration failure on Windows #9491

merged 4 commits into from
Sep 10, 2018

Conversation

ngotchac
Copy link
Contributor

@ngotchac ngotchac commented Sep 7, 2018

Fixes #9106

The issue would only arise on Windows: the files used for the Blooms database were not properly closed before restoring the snapshot DB. Thus windows would fail to move the directories around.

In addition to this PR, having paritytech/parity-common#53 and debris/fs-swap#8 would be great!

@ngotchac ngotchac added A0-pleasereview 🤓 Pull request needs code review. M4-core ⛓ Core client code / Rust. labels Sep 7, 2018
@ForauDNB
Copy link

ForauDNB commented Sep 7, 2018

Thankyou for bringing up this issue for investigation. Is anybody aware of any manual workarounds in the mean time?

@ngotchac
Copy link
Contributor Author

ngotchac commented Sep 7, 2018

Sadly there are no manual fixes other than not using Windows or using an older Parity version :/

@ForauDNB
Copy link

ForauDNB commented Sep 7, 2018

Ok thanks. I'm not too worried as for me this only affects mainnet, ropsten is syncing fine and that's all I need at the moment for solidity development purposes :). Although I may just end up dual booting my new machine. Thanks for your help, keep up the great work 👍

@5chdn 5chdn added this to the 2.1 milestone Sep 8, 2018
@5chdn 5chdn mentioned this pull request Sep 8, 2018
8 tasks
Copy link
Collaborator

@dvdplm dvdplm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm modulo spelling nits

self.blooms().close()?;
self.trace_blooms().close()?;

// Restore the key_value BD
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/BD/DB/

impl DatabaseFiles {
/// Open the blooms db files
pub fn open(path: &PathBuf) -> io::Result<DatabaseFiles> {
// let path = path.as_ref();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

}

impl DatabaseFiles {
/// Open the blooms db files
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/blooms db files/bloom db files/ ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's called blooms-db :p

})
}

pub fn flush(&mut self) -> io::Result<()> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this have to be pub? It'd be nice if flushing was taken care of internally if&when needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably flush on drop, but also keep the explicit flushing.

self.top = File::open(self.path.join("top.bdb"))?;
self.mid = File::open(self.path.join("mid.bdb"))?;
self.bot = File::open(self.path.join("bot.bdb"))?;
self.db_files = Some(DatabaseFiles::open(&self.path)?);
Ok(())
}

/// Insert consecutive blooms into database starting with positon from.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/…starting with position from/…starting at the given position/

Ok(())
}

pub fn iterator_from(&mut self, pos: Positions) -> io::Result<DatabaseFilesIterator> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a curiosity: This method looks a little like the std::io::Seek trait. Would it be possible to refactor things so that Positions become Position and consist of single u64 (which is then shifted properly to form the three variants needed for top, middle and bottom, kind of what happens in the insert_blooms method) and then impl seek for DatabaseFilesIterator? Not sure what we'd gain, and not in scope for this bug-fix PR but interested in your thoughts! :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not actually quite sure how this blooms-db work so I'd say it's (as you said) out-of-scop for this PR, but @debris might have an opinion on this

for (index, bloom) in (from..).into_iter().zip(blooms.map(Into::into)) {
let pos = Positions::from_index(index);

// constant forks make lead to increased ration of false positives in bloom filters
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/constant forks make lead to increased ration of /Constant forks may lead to increased ratio of/


// constant forks make lead to increased ration of false positives in bloom filters
// since we do not rebuild top or mid level, but we should not be worried about that
// most of the time events at block n(a) occur also on block n(b) or n+1(b)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/most of the times/because most of the time/

Copy link
Contributor

@andresilva andresilva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Nice find :)

})
}

pub fn flush(&mut self) -> io::Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably flush on drop, but also keep the explicit flushing.

if let Some(ref mut db_files) = self.db_files {
db_files.flush()?;
}
self.db_files = None;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we impl Drop for DatabaseFiles we can avoid the explicit flush above right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep !

Copy link
Collaborator

@sorpaas sorpaas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few grumbles/questions:

  • Rust's std::fs::File design is to automatically close the file on Drop. Would we want to remove the Option/reopen here -- just drop the value and then recreate a new handle?
  • I think there may be a simpler fix for this, in https://github.com/paritytech/parity-ethereum/pull/9491/files#diff-9d32ce4d31852f1010ba2899d38f245dL75, we can just first drop all self.top, self.mid, self.bot handles before open files again. I think the issue is just that Rust tries to call drop after File::open, but we should call drop before it.

/// Database path
path: PathBuf,
}

impl Database {
/// Opens blooms database.
pub fn open<P>(path: P) -> io::Result<Database> where P: AsRef<Path> {
let path = path.as_ref();
let path: PathBuf = path.as_ref().to_owned();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this changed to take owned value? Path also has join which may just be enough.

@ngotchac
Copy link
Contributor Author

@sorpaas So the issue is that (on Windows) we need to first close the handles to the blooms-db files before being able to move the key_value DB (by calling the restore method): so first close the blooms handles, call restore on the kvdb and then re-open the handles. So you can't just drop the values and re-open them, since we need to do something between the two.
I found that the minimal changes would be to add this close method to the blooms-db, which already has the path value stored in struct Database.
Does this answer your comment?

mid: File::open(path.join("mid.bdb"))?,
bot: File::open(path.join("bot.bdb"))?,
path: path.to_owned(),
db_files: Some(DatabaseFiles::open(&path)?),

This comment was marked as resolved.

}

pub fn iterator_from(&mut self, pos: Positions) -> io::Result<DatabaseFilesIterator> {
Ok(DatabaseFilesIterator{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a whitespace between DatabaseFilesIterator and {.

@sorpaas
Copy link
Collaborator

sorpaas commented Sep 10, 2018

Understood. Indeed we need close. Have two final grumbles!

@sorpaas sorpaas added A8-looksgood 🦄 Pull request is reviewed well. and removed A0-pleasereview 🤓 Pull request needs code review. labels Sep 10, 2018
@ordian ordian merged commit baf5be0 into master Sep 10, 2018
@ordian ordian deleted the ng-fix-restore branch September 10, 2018 15:22
sorpaas pushed a commit that referenced this pull request Sep 10, 2018
* Close Blooms DB files before DB restoration

* PR Grumbles I

* PR Grumble

* Grumble
5chdn added a commit that referenced this pull request Sep 10, 2018
* parity-version: bump beta to 2.0.4

* [light/jsonrpc] Provide the actual account for `eth_coinbase` RPC and unify error handeling for light and full client (#9383)

* Provide the actual `account` for eth_coinbase

The previous implementation always provided the `zero address` on
`eth_coinbase` RPC. Now, instead the actual address is returned on
success or an error when no account(s) is found!

* full client `eth_coinbase` return err

In the full-client return an error when no account is found instead of
returning the `zero address`

* Remove needless blocks on single import

* Remove needless `static` lifetime on const

* Fix `rpc_eth_author` test

* parity: print correct keys path on startup (#9501)

* aura: don't report skipped primaries when empty steps are enabled (#9435)

* Only check warp syncing for eth_getWorks (#9484)

* Only check warp syncing for eth_getWorks

* Use SyncStatus::is_snapshot_syncing

* Fix Snapshot restoration failure on Windows (#9491)

* Close Blooms DB files before DB restoration

* PR Grumbles I

* PR Grumble

* Grumble
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A8-looksgood 🦄 Pull request is reviewed well. M4-core ⛓ Core client code / Rust.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DB atomic swap failed: renameat2 failed with code: 22 at the end of a warp sync
7 participants