From 8ae1a5f81099930bb996aa360f6b1315390c116e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Sun, 1 Aug 2021 17:37:48 +0300 Subject: [PATCH] FS: Explicit File::release() after reads/writes are done The file system has been designed to not know how many files are currently in use, but NativeFile has an operating system specific limitation on the maximum number of open files. Instead of trying to keep track of all open native files, ensure the handles are closed when file access is done. There were threading issues trying to flush open files from a thread while another thread is still accessing the file, or attempting to do its own flush. File::release() releases all the internal buffers and resources, so it encompasses write flushing but also closing of the file handles after reading. The idea here is for users to call File::release() after they're done with a file. Certain operations like Reader/Writer being destroyed will cause an automatic release. --- .../client/src/audio/base/audiosystem.cpp | 4 +- doomsday/apps/client/src/con_config.cpp | 4 - .../apps/client/src/ui/widgets/gamewidget.cpp | 2 +- .../libs/core/include/de/archiveentryfile.h | 2 +- doomsday/libs/core/include/de/archivefolder.h | 2 +- doomsday/libs/core/include/de/file.h | 21 +++-- doomsday/libs/core/include/de/nativefile.h | 2 +- doomsday/libs/core/include/de/reader.h | 3 + doomsday/libs/core/include/de/writer.h | 3 + doomsday/libs/core/src/core/filelogsink.cpp | 2 +- doomsday/libs/core/src/data/bank.cpp | 2 +- doomsday/libs/core/src/data/block.cpp | 10 +++ doomsday/libs/core/src/data/profiles.cpp | 2 +- doomsday/libs/core/src/data/reader.cpp | 9 +++ doomsday/libs/core/src/data/refuge.cpp | 2 +- doomsday/libs/core/src/data/writer.cpp | 8 ++ .../core/src/filesys/archiveentryfile.cpp | 4 +- .../libs/core/src/filesys/archivefeed.cpp | 1 - .../libs/core/src/filesys/archivefolder.cpp | 4 +- doomsday/libs/core/src/filesys/file.cpp | 16 ++-- doomsday/libs/core/src/filesys/filesystem.cpp | 2 +- doomsday/libs/core/src/filesys/nativefile.cpp | 76 ++++--------------- .../core/src/filesys/remote/remotefile.cpp | 2 +- .../libs/core/src/scripting/bindings_core.cpp | 2 +- .../libs/doomsday/src/filesys/fs_util.cpp | 2 +- .../libs/doomsday/src/resource/databundle.cpp | 4 +- .../doomsday/src/resource/lumpcatalog.cpp | 12 ++- .../libs/common/src/game/gamesession.cpp | 7 +- doomsday/libs/gloom/src/world/mapimport.cpp | 10 +-- .../tools/savegametool/src/id1translator.cpp | 1 - .../savegametool/src/nativetranslator.cpp | 1 - 31 files changed, 113 insertions(+), 109 deletions(-) diff --git a/doomsday/apps/client/src/audio/base/audiosystem.cpp b/doomsday/apps/client/src/audio/base/audiosystem.cpp index ec639a62d8..56979d899f 100644 --- a/doomsday/apps/client/src/audio/base/audiosystem.cpp +++ b/doomsday/apps/client/src/audio/base/audiosystem.cpp @@ -740,7 +740,7 @@ DE_PIMPL(AudioSystem) Block buf(hndl->length()); hndl->read(buf.data(), buf.size()); file << buf; - file.flush(); + file.release(); return iMusic->PlayFile(file.as().nativePath(), looped); } else if (iMusic->Play && iMusic->SongBuffer) @@ -790,7 +790,7 @@ DE_PIMPL(AudioSystem) Block buf(lump.size()); lump.read(buf.data(), 0, lump.size()); midi << M_Mus2Midi(buf); - midi.flush(); + midi.release(); //M_Free(buf); buf = nullptr; return forAllInterfaces(AUDIO_IMUSIC, [&midi, &looped] (void *ifs) diff --git a/doomsday/apps/client/src/con_config.cpp b/doomsday/apps/client/src/con_config.cpp index 0c159378ad..b4067c04df 100644 --- a/doomsday/apps/client/src/con_config.cpp +++ b/doomsday/apps/client/src/con_config.cpp @@ -177,8 +177,6 @@ static bool writeConsoleState(const Path &filePath) out.writeText("\n#\n# ALIASES\n#\n\n"); writeAliasesToFile(out); - - file.flush(); } catch (const Error &er) { @@ -244,8 +242,6 @@ static bool writeBindingsState(const Path &filePath) return LoopContinue; }); - - file.flush(); return true; } catch (const Error &er) diff --git a/doomsday/apps/client/src/ui/widgets/gamewidget.cpp b/doomsday/apps/client/src/ui/widgets/gamewidget.cpp index 717c6ab68f..0da088cf7c 100644 --- a/doomsday/apps/client/src/ui/widgets/gamewidget.cpp +++ b/doomsday/apps/client/src/ui/widgets/gamewidget.cpp @@ -257,7 +257,7 @@ void GameWidget::renderCubeMap(uint size, const String &outputImagePath) File &outFile = FS::get().root().replaceFile(uniquePath); outFile << buf; - outFile.flush(); + outFile.release(); LOG_GL_MSG("Cube map saved to \"%s\"") << outFile.correspondingNativePath(); } diff --git a/doomsday/libs/core/include/de/archiveentryfile.h b/doomsday/libs/core/include/de/archiveentryfile.h index 73e20b5aef..9e931fd31a 100644 --- a/doomsday/libs/core/include/de/archiveentryfile.h +++ b/doomsday/libs/core/include/de/archiveentryfile.h @@ -62,7 +62,7 @@ class DE_PUBLIC ArchiveEntryFile : public ByteArrayFile * manual flushing this occurs automatically when the root ArchiveFeed * instance is deleted. */ - void flush() override; + void release() const override; Block metaId() const override; diff --git a/doomsday/libs/core/include/de/archivefolder.h b/doomsday/libs/core/include/de/archivefolder.h index 5ef41aeda9..773c5fa62f 100644 --- a/doomsday/libs/core/include/de/archivefolder.h +++ b/doomsday/libs/core/include/de/archivefolder.h @@ -51,7 +51,7 @@ class DE_PUBLIC ArchiveFolder : public Folder virtual ~ArchiveFolder(); - void flush(); + void release() const; String describe() const; diff --git a/doomsday/libs/core/include/de/file.h b/doomsday/libs/core/include/de/file.h index dddbca221a..dea39028d5 100644 --- a/doomsday/libs/core/include/de/file.h +++ b/doomsday/libs/core/include/de/file.h @@ -63,7 +63,7 @@ class Feed; * Subclasses have some special requirements for their destructors: * - deindex() must be called in all subclass destructors so that the instances indexed * under the subclasses' type are removed from the file system's index, too. - * - The file must be automatically flushed before it gets destroyed (see flush()). + * - The file must be automatically flushed before it gets destroyed (see release()). * - The deletion audience must be notified and @c audienceForDeletion must be cleared * afterwards. * @@ -148,14 +148,21 @@ class DE_PUBLIC File : public filesys::Node, public IIOStream, public IObject * Remove this file from its file system's index. */ virtual void deindex(); - + /** - * Commits any buffered changes to the content of the file. All subclasses of File - * must make sure they flush themselves right before they get deleted. Subclasses - * must also flush themselves when a file in write mode is changed to read-only mode, - * if necessary. + * Commits any buffered changes to the content of the file and releases any internal + * buffers and temporary resources. + * + * All subclasses of File must make sure they release themselves right before they get + * deleted. Subclasses must also release themselves when a file in write mode is changed + * to read-only mode, if necessary. + * + * For example, native files need to close their native file handles. This should always + * be called after one is finished reading or writing a file, so resources are not + * needlessly kept around. However, if this is called too early, the file may need to + * reopen handles and reallocate buffers, degrading performance. */ - virtual void flush(); + virtual void release() const; /** * Empties the contents of the file. diff --git a/doomsday/libs/core/include/de/nativefile.h b/doomsday/libs/core/include/de/nativefile.h index e6ba32e087..7b491ff16d 100644 --- a/doomsday/libs/core/include/de/nativefile.h +++ b/doomsday/libs/core/include/de/nativefile.h @@ -53,7 +53,7 @@ class DE_PUBLIC NativeFile : public ByteArrayFile Block metaId() const; void clear(); - void flush(); + void release() const; /** * Returns the native path of the file. diff --git a/doomsday/libs/core/include/de/reader.h b/doomsday/libs/core/include/de/reader.h index 5c93b1cfe2..54bfe52721 100644 --- a/doomsday/libs/core/include/de/reader.h +++ b/doomsday/libs/core/include/de/reader.h @@ -39,6 +39,9 @@ class IIStream; * a IByteArray or IIStream interface). Byte order defaults to little-endian * but can be changed to big-endian. * + * When a Reader is destroyed, the source file is automatically released, + * if there is one. + * * Note about versioning: readers must be prepared to support old versions of * the serialization protocol in addition to the latest one for backwards * compatibility. diff --git a/doomsday/libs/core/include/de/writer.h b/doomsday/libs/core/include/de/writer.h index 50599f3e68..e2e84b1ab4 100644 --- a/doomsday/libs/core/include/de/writer.h +++ b/doomsday/libs/core/include/de/writer.h @@ -40,6 +40,9 @@ class IOStream; * array object (anything with a IByteArray interface). Defaults to * little-endian byte order. * + * When a Writer is destroyed, the destination file is automatically released, + * if there is one. + * * Note about versioning: when instructed to include a header, Writer always * uses the latest version of serialization. * diff --git a/doomsday/libs/core/src/core/filelogsink.cpp b/doomsday/libs/core/src/core/filelogsink.cpp index ac0e2fd5bc..b4eaba6c8a 100644 --- a/doomsday/libs/core/src/core/filelogsink.cpp +++ b/doomsday/libs/core/src/core/filelogsink.cpp @@ -41,7 +41,7 @@ void FileLogSink::flush() { if (_file) { - _file->flush(); + _file->release(); } } diff --git a/doomsday/libs/core/src/data/bank.cpp b/doomsday/libs/core/src/data/bank.cpp index 79601ba324..d7ac748d99 100644 --- a/doomsday/libs/core/src/data/bank.cpp +++ b/doomsday/libs/core/src/data/bank.cpp @@ -288,7 +288,7 @@ DE_PIMPL(Bank) Writer(*serial).withHeader() << source->modifiedAt() << *data->asSerializable(); - serial->flush(); + serial->release(); } catch (...) { diff --git a/doomsday/libs/core/src/data/block.cpp b/doomsday/libs/core/src/data/block.cpp index 25cbf34763..cab3f2db31 100644 --- a/doomsday/libs/core/src/data/block.cpp +++ b/doomsday/libs/core/src/data/block.cpp @@ -42,6 +42,11 @@ Block::Block(const IByteArray &other) other.get(0, data(), num); // Ensure it's null-terminated. data()[num] = 0; + if (const File *f = maybeAs(other)) + { + // We are done with this file. + f->release(); + } } Block::Block(const Block &other) @@ -126,6 +131,11 @@ void Block::copyFrom(const IByteArray &array, Offset at, Size count) // Read the other's data directly into our data buffer. resize(count); array.get(at, data(), count); + if (const File *f = maybeAs(array)) + { + // We are done with this file. + f->release(); + } } void Block::resize(Size size) diff --git a/doomsday/libs/core/src/data/profiles.cpp b/doomsday/libs/core/src/data/profiles.cpp index 325e6a96c4..6c0669d8a9 100644 --- a/doomsday/libs/core/src/data/profiles.cpp +++ b/doomsday/libs/core/src/data/profiles.cpp @@ -273,7 +273,7 @@ void Profiles::serialize() const // Create the pack and update the file system. File &outFile = App::rootFolder().replaceFile(d->fileName()); outFile << Block(os.str()); - outFile.flush(); // we're done + outFile.release(); // we're done LOG_VERBOSE("Wrote \"%s\" with %i profile%s") << d->fileName() << count << (count != 1? "s" : ""); diff --git a/doomsday/libs/core/src/data/reader.cpp b/doomsday/libs/core/src/data/reader.cpp index 6c3cd462ed..2c24ab50d6 100644 --- a/doomsday/libs/core/src/data/reader.cpp +++ b/doomsday/libs/core/src/data/reader.cpp @@ -22,6 +22,7 @@ #include "de/block.h" #include "de/iserializable.h" #include "de/iistream.h" +#include "de/file.h" #include "de/fixedbytearray.h" #include "de/byterefarray.h" #include "de/byteorder.h" @@ -70,6 +71,14 @@ DE_PIMPL_NOREF(Reader) upgradeToByteArray(); } + ~Impl() + { + if (const File *f = maybeAs(source)) + { + f->release(); + } + } + /** * Byte arrays provide more freedom with reading. If the streaming object * happens to support the byte array interface, Reader will use it instead. diff --git a/doomsday/libs/core/src/data/refuge.cpp b/doomsday/libs/core/src/data/refuge.cpp index 1ea1ad06fb..1c4bad8115 100644 --- a/doomsday/libs/core/src/data/refuge.cpp +++ b/doomsday/libs/core/src/data/refuge.cpp @@ -82,7 +82,7 @@ void Refuge::write() const Writer(App::mutablePersistentData().entryBlock(d->persistentPath)).withHeader() << d->names; - App::persistPackFolder().flush(); + App::persistPackFolder().release(); } } diff --git a/doomsday/libs/core/src/data/writer.cpp b/doomsday/libs/core/src/data/writer.cpp index 61e86df855..be702a7629 100644 --- a/doomsday/libs/core/src/data/writer.cpp +++ b/doomsday/libs/core/src/data/writer.cpp @@ -61,6 +61,14 @@ DE_PIMPL_NOREF(Writer) offset (other.offset ), fixedOffset(other.fixedOffset) {} + + ~Impl() + { + if (File *f = maybeAs(destination)) + { + f->release(); + } + } void write(const IByteArray::Byte *ptr, dsize size) { diff --git a/doomsday/libs/core/src/filesys/archiveentryfile.cpp b/doomsday/libs/core/src/filesys/archiveentryfile.cpp index 51da7f4375..5e81765bbf 100644 --- a/doomsday/libs/core/src/filesys/archiveentryfile.cpp +++ b/doomsday/libs/core/src/filesys/archiveentryfile.cpp @@ -100,9 +100,9 @@ void ArchiveEntryFile::clear() setStatus(st); } -void ArchiveEntryFile::flush() +void ArchiveEntryFile::release() const { - ByteArrayFile::flush(); + ByteArrayFile::release(); if (ArchiveFeed *feed = maybeAs(originFeed())) { feed->rewriteFile(); diff --git a/doomsday/libs/core/src/filesys/archivefeed.cpp b/doomsday/libs/core/src/filesys/archivefeed.cpp index c3e069fb24..0a0ff58c39 100644 --- a/doomsday/libs/core/src/filesys/archivefeed.cpp +++ b/doomsday/libs/core/src/filesys/archivefeed.cpp @@ -131,7 +131,6 @@ DE_PIMPL(ArchiveFeed) file->clear(); Writer(*file) << *arch; - file->flush(); } else { diff --git a/doomsday/libs/core/src/filesys/archivefolder.cpp b/doomsday/libs/core/src/filesys/archivefolder.cpp index c5b9b994e4..8cae23a8e0 100644 --- a/doomsday/libs/core/src/filesys/archivefolder.cpp +++ b/doomsday/libs/core/src/filesys/archivefolder.cpp @@ -34,9 +34,9 @@ ArchiveFolder::~ArchiveFolder() deindex(); } -void ArchiveFolder::flush() +void ArchiveFolder::release() const { - Folder::flush(); + Folder::release(); primaryFeed()->as().rewriteFile(); } diff --git a/doomsday/libs/core/src/filesys/file.cpp b/doomsday/libs/core/src/filesys/file.cpp index 71fbe0b18a..1ac423e2a6 100644 --- a/doomsday/libs/core/src/filesys/file.cpp +++ b/doomsday/libs/core/src/filesys/file.cpp @@ -75,7 +75,7 @@ File::~File() DE_NOTIFY(Deletion, i) i->fileBeingDeleted(*this); - flush(); + release(); if (d->source != this) { // If we own a source, get rid of it. @@ -95,8 +95,14 @@ void File::deindex() fileSystem().deindex(*this); } -void File::flush() -{} +void File::release() const +{ + const File *src = source(); + if (src != this) + { + src->release(); + } +} void File::clear() { @@ -283,7 +289,7 @@ void File::setMode(const Flags &newMode) // Implicitly flush the file before switching away from write mode. if (d->mode.testFlag(Write) && !newMode.testFlag(Write)) { - flush(); + release(); } if (this != d->source) @@ -349,7 +355,7 @@ File *File::reinterpret() deindex(); } - original->flush(); + original->release(); File *result = fileSystem().interpret(original); // The interpreter should use whatever origin feed the file was previously using. diff --git a/doomsday/libs/core/src/filesys/filesystem.cpp b/doomsday/libs/core/src/filesys/filesystem.cpp index b032a05ac7..aeffca17f5 100644 --- a/doomsday/libs/core/src/filesys/filesystem.cpp +++ b/doomsday/libs/core/src/filesys/filesystem.cpp @@ -314,7 +314,7 @@ File &FileSystem::copySerialized(const String &sourcePath, const String &destina File *dest = &fs.root().replaceFile(destinationPath); *dest << contents; - dest->flush(); + dest->release(); if (behavior & ReinterpretDestination) { diff --git a/doomsday/libs/core/src/filesys/nativefile.cpp b/doomsday/libs/core/src/filesys/nativefile.cpp index 34020ad61c..5a21fa029a 100644 --- a/doomsday/libs/core/src/filesys/nativefile.cpp +++ b/doomsday/libs/core/src/filesys/nativefile.cpp @@ -21,57 +21,15 @@ #include "de/directoryfeed.h" #include "de/guard.h" #include "de/math.h" - +#include "de/waitable.h" #include +#include // debug prints #include #include namespace de { -struct OpenFiles : public Lockable -{ - // We need to keep track of how many native files are open at once, because - // operating systems have a hard limit on this. We shouldn't open and close - // a file for each read/write, because that's very slow, but we shouldn't keep - // files open for a long time either. Note that files may be accessed - // from multiple threads, although usually not simultanously. - - static constexpr int MAX_COUNT = 32; - - std::deque> currentlyOpen; - - void insert(NativeFile &file) - { - try - { - SafePtr toFlush; - { - DE_GUARD(this); - currentlyOpen.push_back(&file); - if (currentlyOpen.size() > MAX_COUNT) - { - toFlush = currentlyOpen.front(); - currentlyOpen.pop_front(); - } - } - toFlush->flush(); - } - catch (const Error &) - { - // Was deleted already. - } - } - - void remove(NativeFile &file) - { - DE_GUARD(this); - std::remove_if(currentlyOpen.begin(), - currentlyOpen.end(), - [&file](const SafePtr &open) { return open == &file; }); - } -}; - -static OpenFiles s_openFiles; +static std::atomic_int s_openFileCount; DE_PIMPL(NativeFile) { @@ -91,9 +49,15 @@ DE_PIMPL(NativeFile) { if (!file) { - // Keep track of how many open files there are. - s_openFiles.insert(self()); -// std::cout << "File opened: " << this << " (" << nativePath.asText() << ")" << std::endl; + // We need to keep track of how many native files are open at once, because + // operating systems have a hard limit on this. We shouldn't open and close + // a file for each read/write, because that's very slow, but we shouldn't keep + // files open for a long time either. Note that files may be accessed + // from multiple threads, although usually not simultanously. + s_openFileCount++; +// std::cout << s_openFileCount << " File opened: " << this << " (" << nativePath.asText() << ") " +// << "thread:" << current_Thread() << std::endl; + assert(s_openFileCount < 50); file = new_File(nativePath.toString()); @@ -121,8 +85,8 @@ DE_PIMPL(NativeFile) { if (file) { - s_openFiles.remove(self()); -// std::cout << "File closed: " << this << std::endl; + s_openFileCount--; +// std::cout << s_openFileCount << " File closed: " << this << std::endl; iReleasePtr(&file); } } @@ -136,7 +100,6 @@ NativeFile::NativeFile(const String &name, const NativePath &nativePath) NativeFile::~NativeFile() { - s_openFiles.remove(*this); DE_GUARD(this); DE_NOTIFY(Deletion, i) i->fileBeingDeleted(*this); @@ -165,17 +128,11 @@ Block NativeFile::metaId() const void NativeFile::close() { - s_openFiles.remove(*this); - DE_GUARD(this); - - flush(); - DE_ASSERT(!d->file); - d->closeFile(); + release(); } -void NativeFile::flush() +void NativeFile::release() const { - s_openFiles.remove(*this); DE_GUARD(this); d->closeFile(); @@ -191,7 +148,6 @@ const NativePath &NativeFile::nativePath() const void NativeFile::clear() { - s_openFiles.remove(*this); DE_GUARD(this); File::clear(); // checks for write access diff --git a/doomsday/libs/core/src/filesys/remote/remotefile.cpp b/doomsday/libs/core/src/filesys/remote/remotefile.cpp index 28f40a6546..0152c2a2d8 100644 --- a/doomsday/libs/core/src/filesys/remote/remotefile.cpp +++ b/doomsday/libs/core/src/filesys/remote/remotefile.cpp @@ -178,7 +178,7 @@ void RemoteFile::download() File &data = cacheFolder.replaceFile(fn); data << d->buffer; d->buffer.clear(); - data.flush(); + data.release(); // Override the last modified time. { diff --git a/doomsday/libs/core/src/scripting/bindings_core.cpp b/doomsday/libs/core/src/scripting/bindings_core.cpp index 1e2a722ae8..3311c4a646 100644 --- a/doomsday/libs/core/src/scripting/bindings_core.cpp +++ b/doomsday/libs/core/src/scripting/bindings_core.cpp @@ -183,7 +183,7 @@ static Value *Function_File_Write(Context &ctx, const Function::ArgumentValues & static Value *Function_File_Flush(Context &ctx, const Function::ArgumentValues &) { - fileInstance(ctx).flush(); + fileInstance(ctx).release(); return nullptr; } diff --git a/doomsday/libs/doomsday/src/filesys/fs_util.cpp b/doomsday/libs/doomsday/src/filesys/fs_util.cpp index 028ee51be6..f802424625 100644 --- a/doomsday/libs/doomsday/src/filesys/fs_util.cpp +++ b/doomsday/libs/doomsday/src/filesys/fs_util.cpp @@ -506,7 +506,7 @@ dd_bool F_DumpFile(File1 &file, const char *outputPath) { File &out = App::rootFolder().replaceFile(dumpPath); out << Block(file.cache(), file.info().size); - out.flush(); + out.release(); file.unlock(); LOG_RES_VERBOSE("%s dumped to %s") << file.name() << out.description(); return true; diff --git a/doomsday/libs/doomsday/src/resource/databundle.cpp b/doomsday/libs/doomsday/src/resource/databundle.cpp index aef8d6da0a..9b0e1334fc 100644 --- a/doomsday/libs/doomsday/src/resource/databundle.cpp +++ b/doomsday/libs/doomsday/src/resource/databundle.cpp @@ -1237,7 +1237,9 @@ bool DataBundle::identifyPackages() const LOG_AS("DataBundle"); try { - return d->identify(); + const bool ok = d->identify(); + asFile().release(); + return ok; } catch (const Error &er) { diff --git a/doomsday/libs/doomsday/src/resource/lumpcatalog.cpp b/doomsday/libs/doomsday/src/resource/lumpcatalog.cpp index 1c9a898e73..a2833bc897 100644 --- a/doomsday/libs/doomsday/src/resource/lumpcatalog.cpp +++ b/doomsday/libs/doomsday/src/resource/lumpcatalog.cpp @@ -43,17 +43,25 @@ DE_PIMPL(LumpCatalog) , packageIds(other.packageIds) , bundles(other.bundles) {} + + ~Impl() + { + for (const auto *bundle : bundles) + { + bundle->asFile().release(); + } + } void clear() { packageIds.clear(); bundles.clear(); } - + void updateBundles() { bundles.clear(); - + for (const auto &pkg : packageIds) { // The package must be available as a file. diff --git a/doomsday/libs/gamekit/libs/common/src/game/gamesession.cpp b/doomsday/libs/gamekit/libs/common/src/game/gamesession.cpp index ebe7b1f449..c4f837aea8 100644 --- a/doomsday/libs/gamekit/libs/common/src/game/gamesession.cpp +++ b/doomsday/libs/gamekit/libs/common/src/game/gamesession.cpp @@ -283,7 +283,6 @@ DE_PIMPL(GameSession) ZipArchive arch; arch.add("Info", composeSaveInfo(metadata).toUtf8()); de::Writer(save) << arch; - save.flush(); // We can now reinterpret and populate the contents of the archive. saved = &save.reinterpret()->as(); @@ -307,7 +306,7 @@ DE_PIMPL(GameSession) //DoomsdayApp::app().gameSessionWasSaved(self(), *saved); //self().setThinkerMapping(nullptr); - saved->flush(); // No need to populate; FS2 Files already in sync with source data. + saved->release(); // No need to populate; FS2 Files already in sync with source data. saved->cacheMetadata(metadata); // Avoid immediately reopening the .save package. return *saved; @@ -1234,7 +1233,7 @@ void GameSession::leaveMap(const res::Uri &nextMapUri, uint nextMapEntryPoint) // Ensure changes are written to disk right away (otherwise would stay // in memory only). - saved->flush(); + saved->release(); } #if __JHEXEN__ @@ -1315,7 +1314,7 @@ void GameSession::leaveMap(const res::Uri &nextMapUri, uint nextMapEntryPoint) //DoomsdayApp::app().gameSessionWasSaved(*this, *saved); //setThinkerMapping(nullptr); - saved->flush(); // Write all changes to the package. + saved->release(); // Write all changes to the package. saved->cacheMetadata(metadata); // Avoid immediately reopening the .save package. } } diff --git a/doomsday/libs/gloom/src/world/mapimport.cpp b/doomsday/libs/gloom/src/world/mapimport.cpp index 2b1ceda57d..9b8675e30a 100644 --- a/doomsday/libs/gloom/src/world/mapimport.cpp +++ b/doomsday/libs/gloom/src/world/mapimport.cpp @@ -438,7 +438,7 @@ void MapImport::exportPackage(const String &packageRootPath) const "@include \n"; // TODO: Include all information known about the map based on the WAD file, etc. f << dei.toUtf8(); - f.flush(); + f.release(); } // Maps included in the pacakge. @@ -452,14 +452,14 @@ void MapImport::exportPackage(const String &packageRootPath) const d->metersPerUnit.x, d->metersPerUnit.y, d->metersPerUnit.z) + "\n}\n"; f << dei.toUtf8(); - f.flush(); + f.release(); } // The map itself. { File &f = maps.replaceFile(d->mapId + ".gloommap"); f << d->map.serialize(); - f.flush(); + f.release(); } // Source index lookup tables. @@ -474,7 +474,7 @@ void MapImport::exportPackage(const String &packageRootPath) const std::ostringstream os; os << lut; f << String(os.str()).toUtf8(); - f.flush(); + f.release(); } // Materials used in the map. @@ -522,7 +522,7 @@ void MapImport::exportPackage(const String &packageRootPath) const File &f = root.replaceFile("materials.dei"); f << String(os.str()); - f.flush(); + f.release(); } } diff --git a/doomsday/tools/savegametool/src/id1translator.cpp b/doomsday/tools/savegametool/src/id1translator.cpp index f3f8340ae7..86861903c1 100644 --- a/doomsday/tools/savegametool/src/id1translator.cpp +++ b/doomsday/tools/savegametool/src/id1translator.cpp @@ -272,6 +272,5 @@ void Id1Translator::convert(Path path) File &outFile = outputFolder().replaceFile(saveName.fileNameWithoutExtension() + ".save"); Writer(outFile) << arch; - outFile.flush(); LOG_MSG("Wrote ") << outFile.as().nativePath().pretty(); } diff --git a/doomsday/tools/savegametool/src/nativetranslator.cpp b/doomsday/tools/savegametool/src/nativetranslator.cpp index 03b2b7ab56..2f4c06c9ee 100644 --- a/doomsday/tools/savegametool/src/nativetranslator.cpp +++ b/doomsday/tools/savegametool/src/nativetranslator.cpp @@ -732,6 +732,5 @@ void NativeTranslator::convert(Path path) File &outFile = outputFolder().replaceFile(saveName.fileNameWithoutExtension() + ".save"); Writer(outFile) << arch; - outFile.flush(); LOG_MSG("Wrote %s") << outFile.description(); }