From e5c3a09502f4a46d352617e0b840f94bfc70abaa Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 19 Sep 2015 13:12:59 +0200 Subject: [PATCH] + for file-based recovery write the data files in worker threads --- src/Base/Writer.cpp | 17 +++++++++- src/Base/Writer.h | 8 ++++- src/Gui/AutoSaver.cpp | 75 +++++++++++++++++++++++++++++++++++++++++-- src/Gui/AutoSaver.h | 1 + 4 files changed, 97 insertions(+), 4 deletions(-) diff --git a/src/Base/Writer.cpp b/src/Base/Writer.cpp index 1955bf883..aa863a593 100644 --- a/src/Base/Writer.cpp +++ b/src/Base/Writer.cpp @@ -113,12 +113,22 @@ void Writer::setMode(const std::string& mode) Modes.insert(mode); } +void Writer::setModes(const std::set& modes) +{ + Modes = modes; +} + bool Writer::getMode(const std::string& mode) const { std::set::const_iterator it = Modes.find(mode); return (it != Modes.end()); } +std::set Writer::getModes() const +{ + return Modes; +} + void Writer::clearMode(const std::string& mode) { std::set::iterator it = Modes.find(mode); @@ -126,6 +136,11 @@ void Writer::clearMode(const std::string& mode) Modes.erase(it); } +void Writer::clearModes() +{ + Modes.clear(); +} + std::string Writer::addFile(const char* Name,const Base::Persistence *Object) { // always check isForceXML() before requesting a file! @@ -261,7 +276,7 @@ FileWriter::~FileWriter() void FileWriter::putNextEntry(const char* file) { std::string fileName = DirName + "/" + file; - this->FileStream.open(fileName.c_str(), std::ios::out); + this->FileStream.open(fileName.c_str(), std::ios::out | std::ios::binary); } bool FileWriter::shouldWrite(const std::string& , const Base::Persistence *) const diff --git a/src/Base/Writer.h b/src/Base/Writer.h index 53f86e383..7979ceb69 100644 --- a/src/Base/Writer.h +++ b/src/Base/Writer.h @@ -83,10 +83,16 @@ public: const std::vector& getFilenames() const; /// Set mode void setMode(const std::string& mode); + /// Set modes + void setModes(const std::set& modes); /// Get mode bool getMode(const std::string& mode) const; + /// Get modes + std::set getModes() const; /// Clear mode void clearMode(const std::string& mode); + /// Clear modes + void clearModes(); //@} /** @name pretty formating for XML */ @@ -187,7 +193,7 @@ public: */ virtual bool shouldWrite(const std::string& name, const Base::Persistence *Object) const; -private: +protected: std::string DirName; std::ofstream FileStream; }; diff --git a/src/Gui/AutoSaver.cpp b/src/Gui/AutoSaver.cpp index 8434325a9..37f40b261 100644 --- a/src/Gui/AutoSaver.cpp +++ b/src/Gui/AutoSaver.cpp @@ -26,7 +26,9 @@ #ifndef _PreComp_ # include # include +# include # include +# include # include # include #endif @@ -52,7 +54,7 @@ using namespace Gui; AutoSaver* AutoSaver::self = 0; AutoSaver::AutoSaver(QObject* parent) - : QObject(parent), timeout(900000), compressed(false) + : QObject(parent), timeout(900000), compressed(true) { App::GetApplication().signalNewDocument.connect(boost::bind(&AutoSaver::slotCreateDocument, this, _1)); App::GetApplication().signalDeleteDocument.connect(boost::bind(&AutoSaver::slotDeleteDocument, this, _1)); @@ -170,7 +172,8 @@ void AutoSaver::saveDocument(const std::string& name, AutoSaveProperty& saver) // write additional files writer.writeFiles(); } - else { + // only create the file if something has changed + else if (!saver.touched.empty()) { std::string fn = doc->TransientDir.getValue(); fn += "/fc_recovery_file.fcstd"; Base::FileInfo tmp(fn); @@ -297,5 +300,73 @@ bool RecoveryWriter::shouldWrite(const std::string& name, const Base::Persistenc return (jt != saver.touched.end()); } +namespace Gui { + +class RecoveryRunnable : public QRunnable +{ +public: + RecoveryRunnable(const std::set& modes, const char* dir, const char* file, const App::Property* p) + : prop(p->Copy()) + , writer(dir) + { + writer.setModes(modes); + writer.putNextEntry(file); + } + virtual ~RecoveryRunnable() + { + delete prop; + } + virtual void run() + { + prop->SaveDocFile(writer); + } + +private: + App::Property* prop; + Base::FileWriter writer; +}; + +} + +void RecoveryWriter::writeFiles(void) +{ +#if 0 + FileWriter::writeFiles(); +#else + // use a while loop because it is possible that while + // processing the files new ones can be added + size_t index = 0; + this->FileStream.close(); + while (index < FileList.size()) { + FileEntry entry = FileList.begin()[index]; + + if (shouldWrite(entry.FileName, entry.Object)) { + std::string filePath = entry.FileName; + std::string::size_type pos = 0; + while ((pos = filePath.find("/", pos)) != std::string::npos) { + std::string dirName = DirName + "/" + filePath.substr(0, pos); + pos++; + Base::FileInfo fi(dirName); + fi.createDirectory(); + } + + // For properties a copy can be created and then this can be written to disk in a thread + if (entry.Object->isDerivedFrom(App::Property::getClassTypeId())) { + const App::Property* prop = static_cast(entry.Object); + QThreadPool::globalInstance()->start(new RecoveryRunnable(getModes(), DirName.c_str(), entry.FileName.c_str(), prop)); + } + else { + std::string fileName = DirName + "/" + entry.FileName; + this->FileStream.open(fileName.c_str(), std::ios::out | std::ios::binary); + entry.Object->SaveDocFile(*this); + this->FileStream.close(); + } + } + + index++; + } +#endif +} + #include "moc_AutoSaver.cpp" diff --git a/src/Gui/AutoSaver.h b/src/Gui/AutoSaver.h index 164398b0c..2b0ae0858 100644 --- a/src/Gui/AutoSaver.h +++ b/src/Gui/AutoSaver.h @@ -106,6 +106,7 @@ public: always returns true. */ virtual bool shouldWrite(const std::string&, const Base::Persistence *) const; + virtual void writeFiles(void); private: AutoSaveProperty& saver;