[Development] QFile: writing via a temporary file
David Faure
david.faure at kdab.com
Thu Jan 5 22:48:32 CET 2012
A very common issue with writing over an existing file, is that in case of
problem in the middle of the writing operation (disk full, application crash,
power failure...) the existing file will be lost. If it contained your thesis,
you might be a bit angry at the Qt application that did that.
The typical solution is to write into a temporary file in the same directory,
and then atomically renaming the temp file to overwrite the existing file.
This then works like a transaction, with the choice to end the writing
operation with a commit (= rename the temp file) or rollback (=erase the temp
file), in case of errors while writing.
Solution 1: using a separate class for handling the QTemporaryFile and the
rename call. KDE's KSaveFile and QtCreator's SaveFile do that. The code of
such a class is quite easy. The downside is that from an API point of view,
it's a bit weird. You have to use this "save file" wrapper class, which is hard
to picture in one's mind, and to name properly for what it does.
API-wise, such a class has methods like commit() and rollback(), to decide
what happens when we're done. If you forget to call either one, the destructor
will decide for you. Funny, in KDE it commits, in QtCreator it rolls back...
Solution 2: how about making this functionality part of QFile itself?
No need to "port to another class" anymore, just enable the safety feature by
calling file.setUseTemporaryFile(true).
This is what I've started doing in the attached patch, but I'd like to gather
feedback before polishing it up.
One issue is that after doing file.setUseTemporaryFile(true) and file.open(),
all the operations on the file object are no longer operating on the given
fileName, but on the "internal" temporary file. That's what we want for writing,
but maybe it could confuse people that remove() or rename() leaves the
existing file untouched? I think it would simply have to be documented: when
enabling the feature, all that happens between open() and close(), happens on
the temp file.
The other question is, would one have to call commit/rollback explicitely, or
should QFile::close() (and the dtor) do the committing?
And how should one rollback? Explicit file.rollback(), or in the existing
file.remove()?
Oswald suggested doing that in close()/remove() directly, and getting rid of
commit()/rollback(). Opinions?
--
David Faure, faure at kde.org, http://www.davidfaure.fr
Sponsored by Nokia to work on KDE, incl. KDE Frameworks 5
-------------- next part --------------
A non-text attachment was scrubbed...
Name: qfile_temp.diff
Type: text/x-patch
Size: 6812 bytes
Desc: not available
URL: <http://lists.qt-project.org/pipermail/development/attachments/20120105/18b1f327/attachment.bin>
More information about the Development
mailing list