-
Notifications
You must be signed in to change notification settings - Fork 22
[Work In Progress, early comments welcome] AtomicFile implementation #64
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
base: master
Are you sure you want to change the base?
Conversation
It currently defines calls necessary for compiling with TDB2 and simply proxies them to regular File. Some naive tests also added to make sure basics work. As part of this change Directory changed to be child of Path. Most of the File methods did not made sense for it. It compiles with TaskWarrior but other users may see missing methods. Most of shared methods should be moved to Path.
Nothing creates .new file yet so this should be no-op.
I've not reviewed the full pull request, but I scanned it to see how it compares with the AtomicFile implementation in timewarrior and I have two general questions.
Since timewarrior uses libshared, it would seem ideal to me if they both use the same AtomicFile implementation (but it doesn't have to be the one that is already in timewarrior if there are issues with it that make it unsuitable for use in taskwarrior). |
Thanks, that's kind of feedback/questions/discussions I wanted.
We can also make it a bit faster by making writes & commits parallel / asynchronous (modern storage can do parallel writes and likes deep IO queues). I understand desire to use the same AtomicFile. I looked into timewarrior database implementation (I don't use it so wasn't familiar) and I can see how timewarrior's implementation makes more sense for that use case. But I think it's less convenient for TaskWarriror, especially in context of potential support pluggable support of binary databases like sqlite. That said, maybe I'm over-complicating things? |
👍
I don't disagree here. Originally, the AtomicFile class was just meant to be a drop-in replacement for File, but ultimately I had envisioned that the set of files that need to be manipulated together would need to be explicitly specified by the user with an
This makes sense to me. Although are you open to something like: AtomicFileSet fileSet;
pending = fileSet.open(...);
completed = fileSet.open(...);
undo = fileSet.open(...);
backlog = fileSet.open(...);
// ...
gather_changes ();
try {
pending.write ();
completed.write ();
undo.write ();
backlog.write ();
fileSet.commit ();
}
catch (...)
{
// rollback handled by AtomicFileSet destructor if commit was not called.
}
👍
I primarily use timewarrior myself, so am in the same boat as you, but just from the other side. Pluggable backends is something that timewarrior has a desire for as well. Although, for the most part, my thoughts are that AtomicFile would be used by the backend, and not as part of the interface. I.e., when someone calls
I don't think so, and I still believe we can come up with an interface that will be usable with both projects if you want to collaborate. |
@vrusinov Just checking if you're waiting on me or not? Would you like me to try and put together a candidate PR? |
Not waiting, and thanks for feedback! Busy, and procrastinating a bit, but hope to get back to this soon. |
Does not seem to be that useful.
Will be useful later when adding fiu tests.
This is the first semi-working implementation of AtomicFile for GothenburgBitFactory/taskwarrior#152. TaskWarrior compiles with this implementation (see atomicfile branch) and all tests pass on my machine. Changes to existing classes are minimal, so most of other libshared users should not be affected. That said, the
Directory
class was rebased to inherit fromPath
. This may cause compilation failures in other projects after submodule is updated.Not ready to be merged yet, but I appreciate any early comments, especially on overall structure.
Few things missing before this can be merged:
AtomicFile::size
Follow-up work which I'd prefer to do in next PRs:
close
tofinalize
orcommit
,truncate
may be better asoverwrite
libshared
users still compile_file.append (std::string("")); // Seek to end of file
should no longer be necessaryTDB2::commit
would doAtomicFile::close
up to four times sequentially, waiting for each fsync() and rename. We can do better by allowing more writes/fsyncs to go in parallel - via async IO or threads.TDB2::commit
. Consider what to do when commit of individual file fails.File
class private and migrating all users toAtomicFile
.