------------------------------------------------------------ revno: 3207 committer: poy <p...@123gen.com> branch nick: trunk timestamp: Thu 2013-02-14 17:25:20 +0100 message: Display progress information when DC++ starts modified: changelog.txt dcpp/DCPlusPlus.cpp dcpp/DCPlusPlus.h dcpp/HashManager.cpp dcpp/HashManager.h dcpp/QueueManager.cpp dcpp/QueueManager.h dcpp/ShareManager.cpp dcpp/ShareManager.h dcpp/Streams.h win32/SplashWindow.cpp win32/SplashWindow.h win32/main.cpp
-- lp:dcplusplus https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk Your team Dcplusplus-team is subscribed to branch lp:dcplusplus. To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt' --- changelog.txt 2013-02-12 22:22:05 +0000 +++ changelog.txt 2013-02-14 16:25:20 +0000 @@ -1,7 +1,7 @@ * Fix status bar parts when the window is too small (poy) * [L#534440] [NMDC] Preserve encodings in some search results (poy) * [ADC] Fix problems after marking oneself as a favorite user -* Cancel the v2->v3 hash upgrade if it takes longer than 26sec (poy) +* Display progress information when DC++ starts (poy) -- 0.810 2013-01-30 -- * Fix a race condition on file list download (thanks bigmuscle) === modified file 'dcpp/DCPlusPlus.cpp' --- dcpp/DCPlusPlus.cpp 2013-01-18 21:28:38 +0000 +++ dcpp/DCPlusPlus.cpp 2013-02-14 16:25:20 +0000 @@ -88,7 +88,7 @@ PluginApiImpl::init(); } -void load(function<void (const string&)> f) { +void load(function<void (const string&)> stepF, function<void (float)> progressF) { SettingsManager::getInstance()->load(); #ifdef _WIN32 @@ -101,9 +101,9 @@ } #endif - auto announce = [&f](const string& str) { - if(f) { - f(str); + auto announce = [&stepF](const string& str) { + if(stepF) { + stepF(str); } }; @@ -111,19 +111,19 @@ ClientManager::getInstance()->loadUsers(); FavoriteManager::getInstance()->load(); - PluginManager::getInstance()->loadPlugins(f); + PluginManager::getInstance()->loadPlugins(stepF); announce(_("Security certificates")); CryptoManager::getInstance()->loadCertificates(); announce(_("Hash database")); - HashManager::getInstance()->startup(); + HashManager::getInstance()->startup(progressF); announce(_("Shared Files")); - ShareManager::getInstance()->refresh(true, false, true); + ShareManager::getInstance()->refresh(true, false, true, progressF); announce(_("Download Queue")); - QueueManager::getInstance()->loadQueue(); + QueueManager::getInstance()->loadQueue(progressF); if(SETTING(GET_USER_COUNTRY)) { announce(_("Country information")); === modified file 'dcpp/DCPlusPlus.h' --- dcpp/DCPlusPlus.h 2013-01-18 21:28:38 +0000 +++ dcpp/DCPlusPlus.h 2013-02-14 16:25:20 +0000 @@ -28,7 +28,7 @@ using std::string; void startup(); -void load(function<void (const string&)> f); +void load(function<void (const string&)> stepF, function<void (float)> progressF); void shutdown(); } // namespace dcpp === modified file 'dcpp/HashManager.cpp' --- dcpp/HashManager.cpp 2013-02-12 22:22:05 +0000 +++ dcpp/HashManager.cpp 2013-02-14 16:25:20 +0000 @@ -21,12 +21,13 @@ #include <boost/scoped_array.hpp> -#include "SimpleXML.h" -#include "LogManager.h" #include "File.h" #include "FileReader.h" +#include "LogManager.h" +#include "ScopedFunctor.h" +#include "SimpleXML.h" +#include "SFVReader.h" #include "ZUtils.h" -#include "SFVReader.h" namespace dcpp { @@ -322,14 +323,27 @@ class HashLoader: public SimpleXMLReader::CallBack { public: - HashLoader(HashManager::HashStore& s) : - store(s), version(HASH_FILE_VERSION), inTrees(false), inFiles(false), inHashStore(false) { - } + HashLoader(HashManager::HashStore& s, const CountedInputStream<false>& countedStream, uint64_t fileSize, function<void (float)> progressF) : + store(s), + countedStream(countedStream), + streamPos(0), + fileSize(fileSize), + progressF(progressF), + version(HASH_FILE_VERSION), + inTrees(false), + inFiles(false), + inHashStore(false) + { } void startTag(const string& name, StringPairList& attribs, bool simple); private: HashManager::HashStore& store; + const CountedInputStream<false>& countedStream; + uint64_t streamPos; + uint64_t fileSize; + function<void (float)> progressF; + int version; string file; @@ -338,13 +352,14 @@ bool inHashStore; }; -void HashManager::HashStore::load() { +void HashManager::HashStore::load(function<void (float)> progressF) { try { Util::migrate(getIndexFile()); - HashLoader l(*this); File f(getIndexFile(), File::READ, File::OPEN); - SimpleXMLReader(&l).parse(f); + CountedInputStream<false> countedStream(&f); + HashLoader l(*this, countedStream, f.getSize(), progressF); + SimpleXMLReader(&l).parse(countedStream); } catch (const Exception&) { // ... } @@ -383,14 +398,6 @@ return false; } - static auto upgradeStart = GET_TICK(); - static auto cancelled = false; - if(cancelled || GET_TICK() > upgradeStart + 26 * 1000) { - // the upgrade is taking too long - cancel the process; the files will be re-hashed. - cancelled = true; - return false; - } - WIN32_FIND_DATA data; // FindFirstFile does a case-insensitive search by default auto handle = ::FindFirstFile(Text::toT(file).c_str(), &data); @@ -462,6 +469,14 @@ static const string sRoot = "Root"; void HashLoader::startTag(const string& name, StringPairList& attribs, bool simple) { + ScopedFunctor([this] { + auto readBytes = countedStream.getReadBytes(); + if(readBytes != streamPos) { + streamPos = readBytes; + progressF(static_cast<float>(readBytes) / static_cast<float>(fileSize)); + } + }); + if (!inHashStore && name == sHashStore) { version = Util::toInt(getAttrib(attribs, sVersion, 0)); if (version == 0) { === modified file 'dcpp/HashManager.h' --- dcpp/HashManager.h 2013-01-18 21:28:38 +0000 +++ dcpp/HashManager.h 2013-02-14 16:25:20 +0000 @@ -19,6 +19,7 @@ #ifndef DCPLUSPLUS_DCPP_HASH_MANAGER_H #define DCPLUSPLUS_DCPP_HASH_MANAGER_H +#include <functional> #include <map> #include <boost/optional.hpp> @@ -34,6 +35,7 @@ namespace dcpp { +using std::function; using std::map; using boost::optional; @@ -83,7 +85,7 @@ */ void rebuild() { hasher.scheduleRebuild(); } - void startup() { hasher.start(); store.load(); } + void startup(function<void (float)> progressF) { hasher.start(); store.load(progressF); } void shutdown() { hasher.shutdown(); @@ -148,7 +150,7 @@ HashStore(); void addFile(const string& aFileName, uint32_t aTimeStamp, const TigerTree& tth, bool aUsed); - void load(); + void load(function<void (float)> progressF); void save(); void rebuild(); === modified file 'dcpp/QueueManager.cpp' --- dcpp/QueueManager.cpp 2013-01-28 21:32:53 +0000 +++ dcpp/QueueManager.cpp 2013-02-14 16:25:20 +0000 @@ -1302,6 +1302,20 @@ } } +int QueueManager::countOnlineSources(const string& aTarget) { + Lock l(cs); + + QueueItem* qi = fileQueue.find(aTarget); + if(!qi) + return 0; + int onlineSources = 0; + for(auto& i: qi->getSources()) { + if(i.getUser().user->isOnline()) + onlineSources++; + } + return onlineSources; +} + void QueueManager::saveQueue(bool force) noexcept { if(!dirty && !force) return; @@ -1383,43 +1397,43 @@ class QueueLoader : public SimpleXMLReader::CallBack { public: - QueueLoader() : cur(NULL), inDownloads(false) { } + QueueLoader(const CountedInputStream<false>& countedStream, uint64_t fileSize, function<void (float)> progressF) : + countedStream(countedStream), + streamPos(0), + fileSize(fileSize), + progressF(progressF), + cur(nullptr), + inDownloads(false) + { } void startTag(const string& name, StringPairList& attribs, bool simple); void endTag(const string& name); + private: + const CountedInputStream<false>& countedStream; + uint64_t streamPos; + uint64_t fileSize; + function<void (float)> progressF; + string target; QueueItem* cur; bool inDownloads; }; -void QueueManager::loadQueue() noexcept { +void QueueManager::loadQueue(function<void (float)> progressF) noexcept { try { - QueueLoader l; Util::migrate(getQueueFile()); File f(getQueueFile(), File::READ, File::OPEN); - SimpleXMLReader(&l).parse(f); + CountedInputStream<false> countedStream(&f); + QueueLoader l(countedStream, f.getSize(), progressF); + SimpleXMLReader(&l).parse(countedStream); dirty = false; } catch(const Exception&) { // ... } } -int QueueManager::countOnlineSources(const string& aTarget) { - Lock l(cs); - - QueueItem* qi = fileQueue.find(aTarget); - if(!qi) - return 0; - int onlineSources = 0; - for(auto& i: qi->getSources()) { - if(i.getUser().user->isOnline()) - onlineSources++; - } - return onlineSources; -} - static const string sDownloads = "Downloads"; static const string sDownload = "Download"; static const string sTempTarget = "TempTarget"; @@ -1436,11 +1450,19 @@ static const string sStart = "Start"; void QueueLoader::startTag(const string& name, StringPairList& attribs, bool simple) { + ScopedFunctor([this] { + auto readBytes = countedStream.getReadBytes(); + if(readBytes != streamPos) { + streamPos = readBytes; + progressF(static_cast<float>(readBytes) / static_cast<float>(fileSize)); + } + }); + QueueManager* qm = QueueManager::getInstance(); if(!inDownloads && name == sDownloads) { inDownloads = true; } else if(inDownloads) { - if(cur == NULL && name == sDownload) { + if(cur == nullptr && name == sDownload) { int64_t size = Util::toInt64(getAttrib(attribs, sSize, 1)); if(size == 0) return; @@ -1469,7 +1491,7 @@ QueueItem* qi = qm->fileQueue.find(target); - if(qi == NULL) { + if(qi == nullptr) { qi = qm->fileQueue.add(target, size, 0, p, tempTarget, added, TTHValue(tthRoot)); if(downloaded > 0) { qi->addSegment(Segment(0, downloaded)); @@ -1508,7 +1530,7 @@ void QueueLoader::endTag(const string& name) { if(inDownloads) { if(name == sDownload) { - cur = NULL; + cur = nullptr; } else if(name == sDownloads) { inDownloads = false; } === modified file 'dcpp/QueueManager.h' --- dcpp/QueueManager.h 2013-01-27 17:45:34 +0000 +++ dcpp/QueueManager.h 2013-02-14 16:25:20 +0000 @@ -132,7 +132,7 @@ int countOnlineSources(const string& aTarget); - void loadQueue() noexcept; + void loadQueue(function<void (float)> progressF) noexcept; void saveQueue(bool force = false) noexcept; string getListPath(const HintedUser& user); === modified file 'dcpp/ShareManager.cpp' --- dcpp/ShareManager.cpp 2013-01-25 20:29:34 +0000 +++ dcpp/ShareManager.cpp 2013-02-14 16:25:20 +0000 @@ -693,7 +693,7 @@ bloom.add(Text::toLower(f.getName())); } -void ShareManager::refresh(bool dirs /* = false */, bool aUpdate /* = true */, bool block /* = false */) noexcept { +void ShareManager::refresh(bool dirs, bool aUpdate, bool block, function<void (float)> progressF) noexcept { if(refreshing.test_and_set()) { LogManager::getInstance()->message(_("File list refresh in progress, please wait for it to finish before trying to refresh again")); return; @@ -701,16 +701,19 @@ update = aUpdate; refreshDirs = dirs; + join(); - try { - start(); - if(block) { - join(); - } else { + + if(block) { + runRefresh(progressF); + + } else { + try { + start(); setThreadPriority(Thread::LOW); + } catch(const ThreadException& e) { + LogManager::getInstance()->message(str(F_("File list refresh failed: %1%") % e.getError())); } - } catch(const ThreadException& e) { - LogManager::getInstance()->message(str(F_("File list refresh failed: %1%") % e.getError())); } } @@ -724,8 +727,12 @@ } int ShareManager::run() { + runRefresh(); + return 0; +} - StringPairList dirs = getDirectories(); +void ShareManager::runRefresh(function<void (float)> progressF) { + auto dirs = getDirectories(); // Don't need to refresh if no directories are shared if(dirs.empty()) refreshDirs = false; @@ -738,12 +745,19 @@ lastFullUpdate = GET_TICK(); vector<pair<Directory::Ptr, string>> newDirs; + + float progressCounter = 0, dirCount = dirs.size(); + for(auto& i: dirs) { - if (checkHidden(i.second)) { + if(checkHidden(i.second)) { auto dp = buildTree(i.second); dp->setName(i.first); newDirs.emplace_back(dp, i.second); } + + if(progressF) { + progressF(++progressCounter / dirCount); + } } { @@ -766,7 +780,6 @@ } refreshing.clear(); - return 0; } void ShareManager::getBloom(ByteVector& v, size_t k, size_t m, size_t h) const { === modified file 'dcpp/ShareManager.h' --- dcpp/ShareManager.h 2013-01-25 20:29:34 +0000 +++ dcpp/ShareManager.h 2013-02-14 16:25:20 +0000 @@ -19,6 +19,7 @@ #ifndef DCPLUSPLUS_DCPP_SHARE_MANAGER_H #define DCPLUSPLUS_DCPP_SHARE_MANAGER_H +#include <functional> #include <map> #include <memory> #include <set> @@ -45,6 +46,7 @@ namespace dcpp { +using std::function; using std::map; using std::set; using std::unique_ptr; @@ -80,7 +82,7 @@ StringList getRealPaths(const string& virtualPath); optional<TTHValue> getTTH(const string& virtualFile) const; - void refresh(bool dirs = false, bool aUpdate = true, bool block = false) noexcept; + void refresh(bool dirs = false, bool aUpdate = true, bool block = false, function<void (float)> progressF = nullptr) noexcept; void setDirty() { xmlDirty = true; } void search(SearchResultList& l, const string& aString, int aSearchType, int64_t aSize, int aFileType, Client* aClient, StringList::size_type maxResults) noexcept; @@ -297,6 +299,7 @@ optional<const ShareManager::Directory::File&> getFile(const string& realPath, Directory::Ptr d = nullptr) noexcept; virtual int run(); + void runRefresh(function<void (float)> progressF = nullptr); // QueueManagerListener virtual void on(QueueManagerListener::FileMoved, const string& realPath) noexcept; === modified file 'dcpp/Streams.h' --- dcpp/Streams.h 2013-01-18 21:28:38 +0000 +++ dcpp/Streams.h 2013-02-14 16:25:20 +0000 @@ -108,6 +108,26 @@ class IOStream : public InputStream, public OutputStream { }; +/** Count how many bytes have been read. */ +template<bool managed> +class CountedInputStream : public InputStream { +public: + CountedInputStream(InputStream* is) : s(is), readBytes(0) { } + virtual ~CountedInputStream() { if(managed) delete s; } + + size_t read(void* buf, size_t& len) { + auto ret = s->read(buf, len); + readBytes += len; + return ret; + } + + uint64_t getReadBytes() const { return readBytes; } + +private: + InputStream* s; + uint64_t readBytes; +}; + template<bool managed> class LimitedInputStream : public InputStream { public: === modified file 'win32/SplashWindow.cpp' --- win32/SplashWindow.cpp 2013-01-18 21:28:38 +0000 +++ win32/SplashWindow.cpp 2013-02-14 16:25:20 +0000 @@ -24,12 +24,14 @@ #include <dcpp/version.h> #include <dwt/DWTException.h> +#include <dwt/widgets/ProgressBar.h> #include "resource.h" #include "WinUtil.h" SplashWindow::SplashWindow() : -dwt::Window(0) + dwt::Window(0), + progress(0) { // 256x icons only work on >= Vista. on failure, try loading a 48x image. try { @@ -58,7 +60,19 @@ } void SplashWindow::operator()(const string& status) { - auto text = str(TF_("Loading DC++, please wait... (%1%)") % Text::toT(status)); + this->status = str(TF_("Loading DC++, please wait... (%1%)") % Text::toT(status)); + progress = 0; + draw(); +} + +void SplashWindow::operator()(float progress) { + this->progress = progress; + draw(); +} + +void SplashWindow::draw() { + auto text = status; + if(progress) { text += _T(" [") + Text::toT(Util::toString(progress * 100.)) + _T("%]"); } // set up sizes. const long spacing { 6 }; // space between the icon and the text @@ -90,8 +104,13 @@ canvas.drawText(text.c_str(), textRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); // set bits within the text rectangle to not be transparent. rgbReserved is the alpha value. - for(long x = textRect.left(), xn = textRect.right(); x < xn; ++x) { - for(long y = textRect.top(), yn = textRect.bottom(); y < yn; ++y) { + // to simulate a progress bar, some bits are made to be semi-opaque. + long pos = textRect.left() + progress * static_cast<float>(textRect.width()); + for(long y = textRect.top(), yn = textRect.bottom(); y < yn; ++y) { + for(long x = textRect.left(); x < pos; ++x) { + bits[x + y * size.cx].rgbReserved = 191; + } + for(long x = pos, xn = textRect.right(); x < xn; ++x) { bits[x + y * size.cx].rgbReserved = 255; } } === modified file 'win32/SplashWindow.h' --- win32/SplashWindow.h 2013-01-18 21:28:38 +0000 +++ win32/SplashWindow.h 2013-02-14 16:25:20 +0000 @@ -27,10 +27,16 @@ virtual ~SplashWindow(); void operator()(const string& status); + void operator()(float progress); private: + void draw(); + long iconSize; dwt::IconPtr icon; + + tstring status; + float progress; }; #endif === modified file 'win32/main.cpp' --- win32/main.cpp 2013-01-18 21:28:38 +0000 +++ win32/main.cpp 2013-02-14 16:25:20 +0000 @@ -133,12 +133,12 @@ } try { - SplashWindow* splash(new SplashWindow); + auto splash = new SplashWindow(); startup(); PluginApiWin::init(); - load([splash](const string& str) { (*splash)(str); }); + load([splash](const string& str) { (*splash)(str); }, [splash](float progress) { (*splash)(progress); }); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE);
_______________________________________________ Mailing list: https://launchpad.net/~linuxdcpp-team Post to : linuxdcpp-team@lists.launchpad.net Unsubscribe : https://launchpad.net/~linuxdcpp-team More help : https://help.launchpad.net/ListHelp