[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