Skip to content

accounts/keystore: fix cache update and TestUpdatedKeyfileContents fa…#15410

Closed
gbotrel wants to merge 2 commits into
ethereum:masterfrom
Consensys:account-cache-tests-fixes
Closed

accounts/keystore: fix cache update and TestUpdatedKeyfileContents fa…#15410
gbotrel wants to merge 2 commits into
ethereum:masterfrom
Consensys:account-cache-tests-fixes

Conversation

@gbotrel
Copy link
Copy Markdown
Contributor

@gbotrel gbotrel commented Nov 1, 2017

fix cache update and TestUpdatedKeyfileContents failing on macOS.
TestUpdatedKeyfileContents was randomly failing on macOS. Root cause: after writing to a file and closing the file handle, we get the fs notify event, we scan the directory and the modified time of the file is not yet updated (and the scanAccount logic relies on that to update the cache), even after the 500ms delay in watch.go.
I believe using the EventInfo from notify library in watch.go:93 to avoid scanning directory and relying on modified time of files would be safer (the event contains the Modified / Created / Deleted file path, yet we scan the whole directory and compare modified times)

Comment thread accounts/keystore/account_cache.go Outdated
filesNow.Add(path)
if modTime.After(prevMtime) {
// on macOS, we get FS notifications before the actual modTime is updated
if modTime.After(prevMtime) || (modTime.Equal(prevMtime) && runtime.GOOS == "darwin") {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe a better fix would be to use modTime.After(prevMtime) || modTime.Equal(prevMtime) on all platforms.
Does that sound good to you?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes if we want to avoid platform specific code, I believe the perf impact is negligible

@holiman
Copy link
Copy Markdown
Contributor

holiman commented Nov 6, 2017

This means rescanning the entire directory again, which is one of the basic problems I wanted to avoid. It is non-neglible when there are hundreds of thousands of accounts. So if there's any other way of doing it (e.g differebt lib), I'd prefer that. Alternatively, keep this fix as a mac only solution. My 5 c.

@gbotrel
Copy link
Copy Markdown
Contributor Author

gbotrel commented Nov 6, 2017

Does it? (= rescan the entire directory). My understanding is that this scan is now triggered only after a FS event is thrown. Meaning something did effectively change in the directory --> meaning iteration i+2 will likely update the new reference modified time:
if modTime.After(newMtime) { newMtime = modTime }

and all the files not changing their modTime won't be picked again.

This was a quick fix, I agree there are more elegant solutions (see first comment --> what about using EventInfo data that contains the path of the file that changed ? but that does change much more than just a line of code)

@fjl
Copy link
Copy Markdown
Contributor

fjl commented Nov 8, 2017

Please remove travis-related changes from this PR.

@gbotrel gbotrel force-pushed the account-cache-tests-fixes branch from 5736f02 to 6407276 Compare November 8, 2017 15:13
@gbotrel
Copy link
Copy Markdown
Contributor Author

gbotrel commented Nov 8, 2017

Did remove the guilty commits with a history rewrite, please ignore GitCop messages :-)

@ethereum ethereum deleted a comment from GitCop Nov 9, 2017
@ethereum ethereum deleted a comment from GitCop Nov 9, 2017
@ethereum ethereum deleted a comment from GitCop Nov 9, 2017
@ethereum ethereum deleted a comment from GitCop Nov 9, 2017
@holiman
Copy link
Copy Markdown
Contributor

holiman commented Nov 9, 2017

Does it? (= rescan the entire directory). My understanding is that this scan is now triggered only after a FS event is thrown. Meaning something did effectively change in the directory --> meaning iteration i+2 will likely update the new reference modified time:
if modTime.After(newMtime) { newMtime = modTime }

and all the files not changing their modTime won't be picked again.

So, the newMtime gets set to whatever file was most recently updated, of all files. So you're right, it will not rescan all of them, just the one(s) that have the latest modiifcation time.

However, that makes me question if this fix will work. Consider the following:

  1. There are a bunch of files, A (mtime:1), B (mtime: 2) and C (mtime: 3).
  2. A scan is made. fc.mtime becomes set to 3 (meaning we needn't bother reading files with mtime before 3).
  3. A is modified, and a rescan is made before the mtime of A is updated.
  4. The file C will be read again, but not A.

Or is there another fs-event triggered once the mtime is changed?

@ethereum ethereum deleted a comment from GitCop Nov 9, 2017
@holiman
Copy link
Copy Markdown
Contributor

holiman commented Nov 25, 2017

Could the problem be that the mtime has only resolution on seconds? Another PR was merged which changed times to 1s in the tests. So this might be fixed already

@holiman
Copy link
Copy Markdown
Contributor

holiman commented Nov 25, 2017

This one: #15498.

@gbotrel
Copy link
Copy Markdown
Contributor Author

gbotrel commented Nov 27, 2017

The other PR don't seem to fix the underlying problem --> the test will pass, but the scenario we mentioned here can still happen and result in a cache not being updated. I agree with your previous comment, my fix is not enough for this to be bulletproof, what about using the EventInfo from notify library? If I have some time will run some tests the coming days.

@holiman
Copy link
Copy Markdown
Contributor

holiman commented Nov 28, 2017

I'll make a PR using the EventInfo thing, and hopefully the buildsystem can tell us how cross-platform portable it is.

@holiman
Copy link
Copy Markdown
Contributor

holiman commented Nov 29, 2017

@gbotrel I can't reproduce the issues myself, but if you're on a Mac, you're more than welcome to test my PR (linked above) and see if it fixes the issue for you.

@gbotrel
Copy link
Copy Markdown
Contributor Author

gbotrel commented Nov 30, 2017

@holiman --> did test your PR #15580 on mac, runs fine 👍 . But it has the other PR (#15498 ) changes in it, making the test quite longer than it was.
I did remove the multiple sleeps

// needed so that modTime of `file` is different to its current value after ioutil.WriteFile
// time.Sleep(1000 * time.Millisecond)

And the tests pass. I believe adding the sleeps was just hiding the test failure, and your PR solves the actual underlying problem.

Closing this PR .

@gbotrel gbotrel closed this Nov 30, 2017
@holiman
Copy link
Copy Markdown
Contributor

holiman commented Dec 1, 2017

Great, thanks for reporting! I'll change those values back, and clean up the PR, and mark it as no-longer-wip.

@gbotrel gbotrel deleted the account-cache-tests-fixes branch August 1, 2018 23: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