refs #600, turned CUrlList into a plain vanilla list

* bundled all load balancing in CFailoverUrlList. "Obtain" functions are non-const, no need of mutable members
This commit is contained in:
Klaus Basan
2016-03-13 00:40:11 +00:00
committed by Mathew Sutcliffe
parent 89d9b3ad39
commit 1a1e4681fe
5 changed files with 56 additions and 77 deletions

View File

@@ -139,7 +139,7 @@ namespace BlackCore
void CSetupReader::ps_readSetup() void CSetupReader::ps_readSetup()
{ {
CUrl url(this->m_bootstrapUrls.getNextWorkingUrl()); CUrl url(this->m_bootstrapUrls.obtainNextWorkingUrl());
if (url.isEmpty()) if (url.isEmpty())
{ {
CLogMessage(this).warning("Cannot read setup, failed URLs: %1") << this->m_bootstrapUrls.getFailedUrls(); CLogMessage(this).warning("Cannot read setup, failed URLs: %1") << this->m_bootstrapUrls.getFailedUrls();
@@ -152,7 +152,7 @@ namespace BlackCore
void CSetupReader::ps_readUpdateInfo() void CSetupReader::ps_readUpdateInfo()
{ {
CUrl url(this->m_updateInfoUrls.getNextWorkingUrl()); CUrl url(this->m_updateInfoUrls.obtainNextWorkingUrl());
if (url.isEmpty()) if (url.isEmpty())
{ {
CLogMessage(this).warning("Cannot read update info, failed URLs: %1") << this->m_updateInfoUrls.getFailedUrls(); CLogMessage(this).warning("Cannot read update info, failed URLs: %1") << this->m_updateInfoUrls.getFailedUrls();

View File

@@ -161,7 +161,7 @@ namespace BlackCore
// round robin for load balancing // round robin for load balancing
// remark: Don't use QThread to run network operations in the background // remark: Don't use QThread to run network operations in the background
// see http://qt-project.org/doc/qt-4.7/qnetworkaccessmanager.html // see http://qt-project.org/doc/qt-4.7/qnetworkaccessmanager.html
QUrl url(m_setup.get().vatsimDataFileUrls().getNextUrl()); QUrl url(m_setup.get().vatsimDataFileUrls().getRandomUrl());
if (url.isEmpty()) { return; } if (url.isEmpty()) { return; }
Q_ASSERT_X(this->m_networkManager, Q_FUNC_INFO, "Missing network manager"); Q_ASSERT_X(this->m_networkManager, Q_FUNC_INFO, "Missing network manager");
QNetworkRequest request(url); QNetworkRequest request(url);

View File

@@ -20,22 +20,11 @@ namespace BlackMisc
CUrlList::CUrlList() { } CUrlList::CUrlList() { }
CUrlList::CUrlList(const CUrlList &other) : CSequence<CUrl>(other) CUrlList::CUrlList(const CUrlList &other) : CSequence<CUrl>(other)
{ { }
*this = other;
}
CUrlList &CUrlList::operator =(const CUrlList &other) CUrlList::CUrlList(const CSequence<CUrl> &other) :
{ CSequence<CUrl>(other)
if (this == &other) { return *this; } { }
QReadLocker readLock(&other.m_lock);
int index = other.m_currentIndexDistributedLoad;
readLock.unlock(); // avoid deadlock
QWriteLocker writeLock(&this->m_lock);
this->m_currentIndexDistributedLoad = index;
return *this;
}
CUrlList::CUrlList(const QStringList &listOfUrls, bool removeDuplicates) CUrlList::CUrlList(const QStringList &listOfUrls, bool removeDuplicates)
{ {
@@ -47,10 +36,6 @@ namespace BlackMisc
} }
} }
CUrlList::CUrlList(const CSequence<CUrl> &other) :
CSequence<CUrl>(other)
{ }
CUrl CUrlList::getRandomUrl() const CUrl CUrlList::getRandomUrl() const
{ {
if (this->isEmpty()) { return CUrl(); } if (this->isEmpty()) { return CUrl(); }
@@ -83,36 +68,6 @@ namespace BlackMisc
return copy.getRandomUrl(); return copy.getRandomUrl();
} }
CUrl CUrlList::getNextUrl(bool randomStart) const
{
if (this->isEmpty()) { return CUrl(); }
if (this->size() == 1) { return this->front();}
if (m_currentIndexDistributedLoad < 0)
{
// random start point
m_currentIndexDistributedLoad = randomStart ?
CMathUtils::randomInteger(0, this->size() - 1) :
0;
}
else
{
m_currentIndexDistributedLoad++;
if (m_currentIndexDistributedLoad >= this->size())
{
m_currentIndexDistributedLoad = 0;
}
}
return (*this)[m_currentIndexDistributedLoad];
}
CUrl CUrlList::getNextUrlWithout(const CUrlList &exclude, bool randomStart) const
{
CUrlList copy(*this);
copy.removeIfIn(exclude);
if (copy.isEmpty()) { return CUrl(); }
return copy.getNextUrl(randomStart);
}
CUrlList CUrlList::appendPath(const QString &path) const CUrlList CUrlList::appendPath(const QString &path) const
{ {
if (path.isEmpty() || this->isEmpty()) { return (*this); } if (path.isEmpty() || this->isEmpty()) { return (*this); }
@@ -144,7 +99,7 @@ namespace BlackMisc
int CUrlList::removeDuplicates() int CUrlList::removeDuplicates()
{ {
if (this->size() < 2) { return 0; } if (this->size() < 2) { return 0; }
CUrlList withoutDuplicates(getWithoutDuplicates()); const CUrlList withoutDuplicates(getWithoutDuplicates());
if (this->size() == withoutDuplicates.size()) { return 0; } if (this->size() == withoutDuplicates.size()) { return 0; }
int r = this->size() - withoutDuplicates.size(); int r = this->size() - withoutDuplicates.size();
(*this) = withoutDuplicates; (*this) = withoutDuplicates;
@@ -187,16 +142,46 @@ namespace BlackMisc
return (m_failedUrls.size() < this->size() && m_failedUrls.size() < m_maxTrials); return (m_failedUrls.size() < this->size() && m_failedUrls.size() < m_maxTrials);
} }
CUrl CFailoverUrlList::getNextWorkingUrl(const CUrl &failedUrl, bool random) CUrl CFailoverUrlList::obtainNextWorkingUrl(bool random, const CUrl &failedUrl)
{ {
if (!failedUrl.isEmpty()) { this->addFailedUrl(failedUrl); } if (!failedUrl.isEmpty()) { this->addFailedUrl(failedUrl); }
if (!hasMoreUrlsToTry()) { return CUrl(); } if (!hasMoreUrlsToTry()) { return CUrl(); }
CUrl url(this->getNextUrlWithout(this->m_failedUrls, random)); const CUrl url(this->obtainNextUrlWithout(random, this->m_failedUrls));
if (CNetworkUtils::canConnect(url)) { return url; } if (CNetworkUtils::canConnect(url)) { return url; }
if (addFailedUrl(url)) { return getNextWorkingUrl(); } if (addFailedUrl(url)) { return obtainNextWorkingUrl(); }
return CUrl(); return CUrl();
} }
CUrl CFailoverUrlList::obtainNextUrl(bool randomStart)
{
if (this->isEmpty()) { return CUrl(); }
if (this->size() == 1) { return this->front();}
if (m_currentIndexDistributedLoad < 0)
{
// random start point
m_currentIndexDistributedLoad = randomStart ?
CMathUtils::randomInteger(0, this->size() - 1) :
0;
}
else
{
m_currentIndexDistributedLoad++;
if (m_currentIndexDistributedLoad >= this->size())
{
m_currentIndexDistributedLoad = 0;
}
}
return (*this)[m_currentIndexDistributedLoad];
}
CUrl CFailoverUrlList::obtainNextUrlWithout(bool randomStart, const CUrlList &exclude) const
{
CFailoverUrlList copy(*this);
copy.removeIfIn(exclude);
if (copy.isEmpty()) { return CUrl(); }
return copy.obtainNextUrl(randomStart);
}
void CFailoverUrlList::reset(int maxTrials) void CFailoverUrlList::reset(int maxTrials)
{ {
this->m_failedUrls.clear(); this->m_failedUrls.clear();

View File

@@ -36,15 +36,12 @@ namespace BlackMisc
//! Copy constructor (because of mutex) //! Copy constructor (because of mutex)
CUrlList(const CUrlList &other); CUrlList(const CUrlList &other);
//! Copy assignment (because of mutex) //! Construct from a base class object.
CUrlList &operator =(const CUrlList &other); CUrlList(const CSequence<CUrl> &other);
//! By list of URLs //! By list of URLs
explicit CUrlList(const QStringList &listOfUrls, bool removeDuplicates = true); explicit CUrlList(const QStringList &listOfUrls, bool removeDuplicates = true);
//! Construct from a base class object.
CUrlList(const CSequence<CUrl> &other);
//! Random location for distributed load //! Random location for distributed load
CUrl getRandomUrl() const; CUrl getRandomUrl() const;
@@ -54,12 +51,6 @@ namespace BlackMisc
//! Random location for distributed load //! Random location for distributed load
CUrl getRandomWithout(const CUrlList &exclude) const; CUrl getRandomWithout(const CUrlList &exclude) const;
//! Round robin with random start point
CUrl getNextUrl(bool randomStart = true) const;
//! Round robin with random start point
CUrl getNextUrlWithout(const CUrlList &exclude, bool randomStart = true) const;
//! Append path to all URLs //! Append path to all URLs
CUrlList appendPath(const QString &path) const; CUrlList appendPath(const QString &path) const;
@@ -71,10 +62,6 @@ namespace BlackMisc
//! Remove duplicated URL and return number of removed elements //! Remove duplicated URL and return number of removed elements
int removeDuplicates(); int removeDuplicates();
private:
mutable int m_currentIndexDistributedLoad = -1; //!< index for random access
mutable QReadWriteLock m_lock; //!< lock (because of mutable members)
}; };
//! URL list with fail support //! URL list with fail support
@@ -105,13 +92,20 @@ namespace BlackMisc
//! More URLs to try //! More URLs to try
bool hasMoreUrlsToTry() const; bool hasMoreUrlsToTry() const;
//! Next utl from this list
CUrl obtainNextUrl(bool randomStart = false);
//! Round robin with random start point
CUrl obtainNextUrlWithout(bool randomStart = false, const CUrlList &exclude = CUrlList()) const;
//! Next working URL, test if it can be connected //! Next working URL, test if it can be connected
CUrl getNextWorkingUrl(const CUrl &failedUrl = CUrl(), bool random = true); CUrl obtainNextWorkingUrl( bool random = false, const CUrl &failedUrl = CUrl());
//! Reset failed URL, allows to set an optional new number of max.trials //! Reset failed URL, allows to set an optional new number of max.trials
void reset(int maxTrials = -1); void reset(int maxTrials = -1);
private: private:
int m_currentIndexDistributedLoad = -1; //!< index for random access
int m_maxTrials = 2; //!< number of max trials int m_maxTrials = 2; //!< number of max trials
CUrlList m_failedUrls; CUrlList m_failedUrls;
}; };

View File

@@ -134,8 +134,8 @@ void CSwiftLauncher::initStyleSheet()
void CSwiftLauncher::displayLatestNews() void CSwiftLauncher::displayLatestNews()
{ {
#ifndef Q_CC_MINGW #ifndef Q_CC_MINGW
CUrlList newsUrls(this->m_setup.get().swiftLatestNewsUrls()); CFailoverUrlList newsUrls(this->m_setup.get().swiftLatestNewsUrls());
QUrl newUrl(newsUrls.getNextUrl()); QUrl newUrl(newsUrls.obtainNextWorkingUrl());
Q_UNUSED(newUrl); Q_UNUSED(newUrl);
/** Qt bug /** Qt bug
@@ -299,7 +299,7 @@ void CSwiftLauncher::ps_loadedSetup(bool success)
CUpdateInfo updateInfo(this->m_updateInfo.get()); CUpdateInfo updateInfo(this->m_updateInfo.get());
QString latestVersion(updateInfo.getLatestVersion()) ; // need to get this from somewhere QString latestVersion(updateInfo.getLatestVersion()) ; // need to get this from somewhere
CUrlList downloadUrls(updateInfo.getDownloadUrls()); CFailoverUrlList downloadUrls(updateInfo.getDownloadUrls());
bool newVersionAvailable = CProject::isNewerVersion(latestVersion) && !downloadUrls.isEmpty(); bool newVersionAvailable = CProject::isNewerVersion(latestVersion) && !downloadUrls.isEmpty();
this->ui->wi_NewVersionAvailable->setVisible(newVersionAvailable); this->ui->wi_NewVersionAvailable->setVisible(newVersionAvailable);
this->ui->wi_NoNewVersion->setVisible(!newVersionAvailable); this->ui->wi_NoNewVersion->setVisible(!newVersionAvailable);
@@ -307,7 +307,7 @@ void CSwiftLauncher::ps_loadedSetup(bool success)
if (!downloadUrls.isEmpty()) if (!downloadUrls.isEmpty())
{ {
CUrl downloadUrl(downloadUrls.getNextUrl()); CUrl downloadUrl(downloadUrls.obtainNextUrl());
QString urlStr(downloadUrl.toQString()); QString urlStr(downloadUrl.toQString());
QString hl("<a href=\"%1\">%2 %3</a>"); QString hl("<a href=\"%1\">%2 %3</a>");
this->ui->lbl_NewVersionUrl->setText(hl.arg(urlStr).arg(urlStr).arg(latestVersion)); this->ui->lbl_NewVersionUrl->setText(hl.arg(urlStr).arg(urlStr).arg(latestVersion));