-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Completely rework save operation #4309
Conversation
try { | ||
Files.deleteIfExists(temporaryFile); | ||
} catch (IOException exception) { | ||
LOGGER.debug("Unable to delete file " + temporaryFile, exception); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For arguments in the logger you can simply use a pair of curly braces {} instead of concat with plus.
https://www.slf4j.org/faq.html#logging_performance
Here and in above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not possible here since the there is no appropriate debug method that also accepts an exception.
} | ||
|
||
// Move temporary file (replace original if it exists) | ||
Files.move(temporaryFile, targetFile, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a move in FileUtil. And you better check if the move was successufl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good point - I don't understand why we have a own move method that actually looks more like a "read and rewrite content"-method. Moreover, the move is successful if there is no thrown exception (I assume).
Yeah, I generally like that you tackle this complex stuff! 👍 We should really test this carefully and also check how it interacts with the FileUpdateMonitor. |
Tobias Diez <notifications@github.com> schrieb am So., 2. Sep. 2018, 10:58:
This is a complete rework of the file writing logic. Since this is the
most essential part of JabRef, I would kindly ask to every
@JabRef/developers <https://github.com/orgs/JabRef/teams/developers> to
have a look at the code (at least on the new AtomicOutputStream which
does the hard work).
Thank you for stepping in!
The new strategy for saving the bib file is as follows:
- Create a backup (with .bak suffix) of the original file in the same
directory as the destination file (if set in preferences).
This is from the early days of JabRef. Why not creating it in %APPDATA% or
/tmp? It confused much of our users.
- Write to a temporary file (with .tmp suffix) in the same directory.
Why not writing to the same file? The only risk is out-of-space, isn't?
When copying things around, we'll have issues with Unix access rights and
ownerships on NFS shares.
- Create a save-backup (with .sav suffix) of the original file (if it
exists) in the same directory.
What is the diff to .bak?
- Move the temporary file to the correct place, overwriting any file
that already exists at that location.
- Delete the save-backup file.
What is not clear to me is how one should handle (almost) concurrent
saving processes of different users to the same file. Is it enough to lock
a file (nio.FileLock) and if yes, which (the tmp?)?
Proposal: lock the .bib and write to it.
… ------------------------------
- Change in CHANGELOG.md described
- Tests created for changes
- Manually tested changed features in running JabRef
- Screenshots added in PR description (for bigger UI changes)
- Ensured that the git commit message is a good one
<https://github.com/joelparkerhenderson/git_commit_message>
- Check documentation status (Issue created for outdated help page at
help.jabref.org <https://github.com/JabRef/help.jabref.org/issues>?)
------------------------------
You can view, comment on, or merge this pull request online at:
#4309
Commit Summary
- Make FileHistory use Paths instead of strings
- Almost completely rewrite save infrastructure
- Merge branch 'master' of https://github.com/JabRef/jabref into
reworkSave
- Fix build
- Fix tests
- Remove file lock
File Changes
- *M* src/jmh/java/org/jabref/benchmarks/Benchmarks.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-0> (26)
- *M* src/main/java/org/jabref/cli/ArgumentProcessor.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-1> (70)
- *M* src/main/java/org/jabref/gui/BasePanel.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-2> (153)
- *M* src/main/java/org/jabref/gui/JabRefFrame.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-3> (3)
- *M* src/main/java/org/jabref/gui/SaveOrderConfigDisplay.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-4> (35)
- *M* src/main/java/org/jabref/gui/collab/ChangeScanner.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-5> (12)
- *M* src/main/java/org/jabref/gui/collab/DatabaseChangeMonitor.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-6> (16)
- *M*
src/main/java/org/jabref/gui/dbproperties/DatabasePropertiesDialog.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-7> (2)
- *M* src/main/java/org/jabref/gui/dialogs/AutosaveUIManager.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-8> (2)
- *M* src/main/java/org/jabref/gui/exporter/SaveAllAction.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-9> (27)
- *M* src/main/java/org/jabref/gui/exporter/SaveDatabaseAction.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-10> (478)
- *M*
src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-11> (33)
- *M* src/main/java/org/jabref/gui/menus/FileHistoryMenu.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-12> (30)
- *M*
src/main/java/org/jabref/gui/shared/SharedDatabaseLoginDialogViewModel.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-13> (2)
- *M*
src/main/java/org/jabref/logic/autosaveandbackup/BackupManager.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-14> (11)
- *A*
src/main/java/org/jabref/logic/exporter/AtomicFileOutputStream.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-15> (199)
- *A* src/main/java/org/jabref/logic/exporter/AtomicFileWriter.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-16> (49)
- *M* src/main/java/org/jabref/logic/exporter/BibDatabaseWriter.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-17> (174)
- *M* src/main/java/org/jabref/logic/exporter/BibtexDatabaseWriter.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-18> (178)
- *D* src/main/java/org/jabref/logic/exporter/FileSaveSession.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-19> (129)
- *M* src/main/java/org/jabref/logic/exporter/MSBibExporter.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-20> (7)
- *M* src/main/java/org/jabref/logic/exporter/SavePreferences.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-21> (38)
- *D* src/main/java/org/jabref/logic/exporter/SaveSession.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-22> (68)
- *D* src/main/java/org/jabref/logic/exporter/StringSaveSession.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-23> (54)
- *M* src/main/java/org/jabref/logic/exporter/TemplateExporter.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-24> (18)
- *D* src/main/java/org/jabref/logic/exporter/VerifyingWriter.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-25> (52)
- *M* src/main/java/org/jabref/logic/importer/OpenDatabase.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-26> (7)
- *D* src/main/java/org/jabref/logic/util/io/FileBasedLock.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-27> (127)
- *M* src/main/java/org/jabref/logic/util/io/FileHistory.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-28> (32)
- *M* src/main/java/org/jabref/logic/util/io/FileUtil.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-29> (3)
- *M* src/main/java/org/jabref/model/metadata/SaveOrderConfig.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-30> (167)
- *M* src/main/java/org/jabref/preferences/JabRefPreferences.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-31> (88)
- *M* src/test/java/org/jabref/gui/AbstractUITest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-32> (9)
- *M* src/test/java/org/jabref/gui/EntryTableTest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-33> (2)
- *M* src/test/java/org/jabref/gui/UndoTest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-34> (2)
- *M* src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-35> (21)
- *M*
src/test/java/org/jabref/logic/exporter/BibtexDatabaseWriterTest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-36> (280)
- *M*
src/test/java/org/jabref/logic/importer/fileformat/BibtexParserTest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-37> (9)
- *M* src/test/java/org/jabref/logic/shared/DBMSProcessorTest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-38> (19)
- *M* src/test/java/org/jabref/logic/util/io/FileHistoryTest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-39> (69)
- *D* src/test/java/org/jabref/model/entry/FileFieldBibEntryTest.java
<https://github.com/JabRef/jabref/pull/4309/files#diff-40> (61)
Patch Links:
- https://github.com/JabRef/jabref/pull/4309.patch
- https://github.com/JabRef/jabref/pull/4309.diff
—
You are receiving this because you are on a team that was mentioned.
Reply to this email directly, view it on GitHub
<#4309>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABTafkNVzVbgv5cwx0WyWSKmAi4HSF0sks5uW52hgaJpZM4WWKs5>
.
|
Thanks @koppor for the valuable input (especially for pointing out that the |
As I experienced this first hand in another project, a locking of the file is practically useless on Unix systems. Even if you grab a write lock, it doesn't stop other processes from accessing the file or writing to it. That's because file locks on Unix are only advisory, e.g.just a signal to other process. |
I included all the feedback from @koppor and @Siedlerchr. Thanks for the good suggestions! |
* upstream/master: Completely rework save operation (#4309)
This is a complete rework of the file writing logic. Since this is the most essential part of JabRef, I would kindly ask to every @JabRef/developers to have a look at the code (at least on the new
AtomicOutputStream
which does the hard work).The new strategy for saving the bib file is as follows:
What is not clear to me is how one should handle (almost) concurrent saving processes of different users to the same file. Is it enough to lock a file (
nio.FileLock
) and if yes, which (the tmp?)?