linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #06573
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3207: Display progress information when DC++ starts
------------------------------------------------------------
revno: 3207
committer: poy <poy@xxxxxxxxxx>
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);