From 0eb1662a0eaf8eee680cab5b913fff3fcc9b8b2f Mon Sep 17 00:00:00 2001 From: Tannin Date: Mon, 5 May 2014 18:24:15 +0200 Subject: - very effective optimization to findfirstfile-calls - several configuration files are now only saved to disk if the content actually changed. This should also get rid of a problem where plugins.txt was re-written immediately after starting the game (causing a conflict with the game) - reduced "noise" from hook.dll - removed some debugging messages --- src/directoryrefresher.cpp | 4 ---- src/mainwindow.cpp | 34 +++++----------------------------- src/mainwindow.h | 2 ++ src/pluginlist.cpp | 9 ++++++--- src/pluginlist.h | 2 ++ src/profile.cpp | 7 +++---- src/profile.h | 1 + src/safewritefile.cpp | 20 ++++++++++++++++++++ src/safewritefile.h | 4 ++++ src/shared/directoryentry.cpp | 29 ++++++++++++++++++++--------- src/shared/directoryentry.h | 6 +++++- 11 files changed, 68 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/directoryrefresher.cpp b/src/directoryrefresher.cpp index 43e13a37..70bcf5b6 100644 --- a/src/directoryrefresher.cpp +++ b/src/directoryrefresher.cpp @@ -93,7 +93,6 @@ void DirectoryRefresher::refresh() //TODO i is the priority here, where higher = more important. the input vector is also sorted by priority but inverted! for (int i = 1; iter != m_Mods.end(); ++iter, ++i) { QString modName = std::get<0>(*iter); -qDebug("load files for mod %s", qPrintable(modName)); try { addModToStructure(m_DirectoryStructure, modName, i, std::get<1>(*iter)); } catch (const std::exception &e) { @@ -103,14 +102,11 @@ qDebug("load files for mod %s", qPrintable(modName)); } std::wstring dataDirectory = GameInfo::instance().getGameDirectory() + L"\\data"; -qDebug("load files for data folder"); m_DirectoryStructure->addFromOrigin(L"data", dataDirectory, 0); emit progress(100); -qDebug("cleanup structure"); cleanStructure(m_DirectoryStructure); -qDebug("all done"); emit refreshed(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b8c357f8..5dc2eb2a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -664,8 +664,9 @@ void MainWindow::saveArchiveList() } } } - archiveFile.commit(); - qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_CurrentProfile->getArchivesFileName()))); + if (archiveFile.commitIfDifferent(m_ArchiveListHash)) { + qDebug("%s saved", qPrintable(QDir::toNativeSeparators(m_CurrentProfile->getArchivesFileName()))); + } } else { qWarning("archive list not initialised"); } @@ -1423,7 +1424,7 @@ HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arg } } - while (m_RefreshProgress->isVisible()) { + while (m_DirectoryUpdate) { ::Sleep(100); QCoreApplication::processEvents(); } @@ -1432,7 +1433,6 @@ HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arg if (m_CurrentProfile != nullptr) { m_CurrentProfile->writeModlistNow(true); } - savePluginList(); // TODO: should also pass arguments if (m_AboutToRun(binary.absoluteFilePath())) { @@ -1443,28 +1443,6 @@ HANDLE MainWindow::spawnBinaryDirect(const QFileInfo &binary, const QString &arg } } -/* -void MainWindow::spawnProgram(const QString &fileName, const QString &argumentsArg, - const QString &profileName, const QDir ¤tDirectory) -{ - QFileInfo binary; - QString arguments = argumentsArg; - QString steamAppID; - try { - const Executable &exe = m_ExecutablesList.find(fileName); - steamAppID = exe.m_SteamAppID; - if (arguments == "") { - arguments = exe.m_Arguments; - } - binary = exe.m_BinaryInfo; - } catch (const std::runtime_error&) { - qWarning("\"%s\" not set up as executable", fileName.toUtf8().constData()); - binary = QFileInfo(fileName); - } - spawnBinaryDirect(binary, arguments, profileName, currentDirectory, steamAppID); -} -*/ - void MainWindow::spawnBinary(const QFileInfo &binary, const QString &arguments, const QDir ¤tDirectory, bool closeAfterStart, const QString &steamAppID) { @@ -2774,8 +2752,6 @@ void MainWindow::refresher_progress(int percent) void MainWindow::directory_refreshed() { - statusBar()->hide(); - DirectoryEntry *newStructure = m_DirectoryRefresher.getDirectoryStructure(); if (newStructure != NULL) { DirectoryEntry *oldStructure = m_DirectoryStructure; @@ -2800,6 +2776,7 @@ void MainWindow::directory_refreshed() ModInfo::Ptr modInfo = ModInfo::getByIndex(i); modInfo->clearCaches(); } + statusBar()->hide(); } @@ -5375,7 +5352,6 @@ void MainWindow::on_bossButton_clicked() HANDLE stdOutWrite = INVALID_HANDLE_VALUE; HANDLE stdOutRead = INVALID_HANDLE_VALUE; createStdoutPipe(&stdOutRead, &stdOutWrite); - HANDLE loot = startBinary(QFileInfo(qApp->applicationDirPath() + "/loot/lootcli.exe"), parameters.join(" "), m_CurrentProfile->getName(), diff --git a/src/mainwindow.h b/src/mainwindow.h index 3caa08ef..3aaf62a5 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -391,6 +391,8 @@ private: std::vector m_RemoveWidget; + uint m_ArchiveListHash; + private slots: void showMessage(const QString &message); diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 534017cd..929e0476 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -391,6 +391,8 @@ void PluginList::writePlugins(const QString &fileName, bool writeUnchecked) cons file->write(textCodec->fromUnicode("# This file was automatically generated by Mod Organizer.\r\n")); + QStringList saveList; + bool invalidFileNames = false; int writtenCount = 0; for (size_t i = 0; i < m_ESPs.size(); ++i) { @@ -401,6 +403,7 @@ void PluginList::writePlugins(const QString &fileName, bool writeUnchecked) cons invalidFileNames = true; qCritical("invalid plugin name %s", m_ESPs[priority].m_Name.toUtf8().constData()); } else { + saveList << m_ESPs[priority].m_Name; file->write(textCodec->fromUnicode(m_ESPs[priority].m_Name)); } file->write("\r\n"); @@ -413,9 +416,9 @@ void PluginList::writePlugins(const QString &fileName, bool writeUnchecked) cons "Please see mo_interface.log for a list of affected plugins and rename them.")); } - file.commit(); - - qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData()); + if (file.commitIfDifferent(m_LastSaveHash[fileName])) { + qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData()); + } } diff --git a/src/pluginlist.h b/src/pluginlist.h index 606d6c68..b7e7e2b4 100644 --- a/src/pluginlist.h +++ b/src/pluginlist.h @@ -29,6 +29,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include #include "pdll.h" #include @@ -278,6 +279,7 @@ private: private: std::vector m_ESPs; + mutable std::map m_LastSaveHash; std::map m_ESPsByName; std::vector m_ESPsByPriority; diff --git a/src/profile.cpp b/src/profile.cpp index 42358b7d..8d02c047 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -147,7 +147,6 @@ void Profile::writeModlistNow(bool onlyOnTimer) const m_SaveTimer->stop(); if (!m_Directory.exists()) return; -#pragma message("right now, this is doing unnecessary saves. Need a flag that says that mod priority, enabled-state or name of a mod has changed") try { QString fileName = getModlistFileName(); @@ -175,9 +174,9 @@ void Profile::writeModlistNow(bool onlyOnTimer) const } } - file.commit(); - - qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData()); + if (file.commitIfDifferent(m_LastModlistHash)) { + qDebug("%s saved", QDir::toNativeSeparators(fileName).toUtf8().constData()); + } } catch (const std::exception &e) { reportError(tr("failed to write mod list: %1").arg(e.what())); return; diff --git a/src/profile.h b/src/profile.h index 5aa77357..df27bb37 100644 --- a/src/profile.h +++ b/src/profile.h @@ -316,6 +316,7 @@ private: QDir m_Directory; + mutable uint m_LastModlistHash; std::vector m_ModStatus; std::vector m_ModIndexByPriority; unsigned int m_NumRegularMods; diff --git a/src/safewritefile.cpp b/src/safewritefile.cpp index 6df8c2b8..626413dd 100644 --- a/src/safewritefile.cpp +++ b/src/safewritefile.cpp @@ -46,3 +46,23 @@ void SafeWriteFile::commit() { m_TempFile.setAutoRemove(false); m_TempFile.close(); } + +bool SafeWriteFile::commitIfDifferent(uint &inHash) { + uint newHash = hash(); + if (newHash != inHash) { + commit(); + inHash = newHash; + return true; + } else { + return false; + } +} + +uint SafeWriteFile::hash() +{ + qint64 pos = m_TempFile.pos(); + m_TempFile.seek(0); + QByteArray data = m_TempFile.readAll(); + m_TempFile.seek(pos); + return qHash(data); +} diff --git a/src/safewritefile.h b/src/safewritefile.h index 56bd7744..06c22acc 100644 --- a/src/safewritefile.h +++ b/src/safewritefile.h @@ -37,6 +37,10 @@ public: void commit(); + bool commitIfDifferent(uint &hash); + + uint hash(); + private: QString m_FileName; QTemporaryFile m_TempFile; diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index a232ea19..6311ba25 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -235,6 +235,9 @@ std::vector FilesOrigin::getFiles() const void FileEntry::addOrigin(int origin, FILETIME fileTime, const std::wstring &archive) { + if (m_Parent != NULL) { + m_Parent->propagateOrigin(origin); + } if (m_Origin == -1) { m_Origin = origin; m_FileTime = fileTime; @@ -385,29 +388,25 @@ std::wstring FileEntry::getRelativePath() const // DirectoryEntry::DirectoryEntry(const std::wstring &name, DirectoryEntry *parent, int originID) : m_OriginConnection(new OriginConnection), - m_Name(name), m_Parent(parent), m_Populated(false), m_Origin(originID), m_TopLevel(true) + m_Name(name), m_Parent(parent), m_Populated(false), m_TopLevel(true) { m_FileRegister.reset(new FileRegister(m_OriginConnection)); + m_Origins.insert(originID); LEAK_TRACE; } DirectoryEntry::DirectoryEntry(const std::wstring &name, DirectoryEntry *parent, int originID, boost::shared_ptr fileRegister, boost::shared_ptr originConnection) : m_FileRegister(fileRegister), m_OriginConnection(originConnection), - m_Name(name), m_Parent(parent), m_Populated(false), m_Origin(originID), m_TopLevel(false) + m_Name(name), m_Parent(parent), m_Populated(false), m_TopLevel(false) { LEAK_TRACE; + m_Origins.insert(originID); } DirectoryEntry::~DirectoryEntry() { -/* if (m_TopLevel) { - if (m_FileRegister.use_count() > 1) { -log("this should not happen"); - delete m_FileRegister.get(); - } - }*/ LEAK_UNTRACE; clear(); } @@ -479,6 +478,14 @@ void DirectoryEntry::addFromBSA(const std::wstring &originName, std::wstring &di m_Populated = true; } +void DirectoryEntry::propagateOrigin(int origin) +{ + m_Origins.insert(origin); + if (m_Parent != NULL) { + m_Parent->propagateOrigin(origin); + } +} + static bool SupportOptimizedFind() { @@ -603,6 +610,10 @@ void DirectoryEntry::removeDir(const std::wstring &path) } } +bool DirectoryEntry::hasContentsFromOrigin(int originID) const +{ + return m_Origins.find(originID) != m_Origins.end(); +} void DirectoryEntry::insertFile(const std::wstring &filePath, FilesOrigin &origin, FILETIME fileTime) { @@ -656,7 +667,7 @@ int DirectoryEntry::anyOrigin() const return res; } } - return m_Origin; + return *(m_Origins.begin()); } diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index b298cdd9..f691603f 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -213,6 +213,8 @@ public: void addFromOrigin(const std::wstring &originName, const std::wstring &directory, int priority); void addFromBSA(const std::wstring &originName, std::wstring &directory, const std::wstring &fileName, int priority); + void propagateOrigin(int origin); + const std::wstring &getName() const; boost::shared_ptr getFileRegister() { return m_FileRegister; } @@ -269,6 +271,8 @@ public: } } + bool hasContentsFromOrigin(int originID) const; + private: DirectoryEntry(const DirectoryEntry &reference); @@ -319,7 +323,7 @@ private: std::vector m_SubDirectories; DirectoryEntry *m_Parent; - int m_Origin; + std::set m_Origins; bool m_Populated; -- cgit v1.3.1