David Faure wrote: > 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.
I agree that this is a common problem and that it would be nice to have a pre-packaged solution to support it. So, in general I'm in favor of adding such a feature to Qt. However... [ reordering solutions for the sake of argument ] > 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. I don't support putting this in QFile as has been suggested as, from my experience with it, this will open a can of worms in maintenance and subtle issues cropping up in user code such as the ones being discussed: what's fileName()? Does it exists() before commit? What do remove() and rename(newName) do? So, let me re-frame the question. What in the current QFile API needs to be exposed in such a class? I think we would be well served by an API that exposes a QIODevice interface plus additional interface for commit/rollback. > The other question is, would one have to call commit/rollback > explicitely, or should QFile::close() (and the dtor) do the > committing? I think commit should require explicit action, for instance, by explicitly calling close(). I don't like having the destructor automatically commit (even if it calls close) though. An exception being thrown in the middle of a save operation could potentially unwind the stack, call the destructor and commit a transaction half-way through. What happens to writes happening after a commit, though? > 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? I wouldn't like remove() to be doing anything different from what it does now: delete the file pointed to by fileName. I'm ok with having implicit rollback done by the destructor. I also don't see a problem with having more explicit rollback functionality. That means, that one would be able to rollback and start over a transaction. > 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... And still those are working examples from the real-world where exactly such solutions were preferred over extending QFile. Cheers, João _______________________________________________ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development