mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-24 02:42:55 +00:00
obtain hosts information without threading
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
This commit is contained in:
parent
bfade642ba
commit
df7225de36
4 changed files with 36 additions and 580 deletions
|
@ -41,27 +41,15 @@
|
|||
|
||||
#include "qhostinfo.h"
|
||||
#include "qhostinfo_p.h"
|
||||
|
||||
#include "QtCore/qscopedpointer.h"
|
||||
#include "qabstracteventdispatcher.h"
|
||||
#include "qcoreapplication.h"
|
||||
#include "qmetaobject.h"
|
||||
#include "qstringlist.h"
|
||||
#include "qthread.h"
|
||||
#include "qurl.h"
|
||||
#include "qnetworksession_p.h"
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
//#define QHOSTINFO_DEBUG
|
||||
// #define QHOSTINFO_DEBUG
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager)
|
||||
#endif
|
||||
Q_GLOBAL_STATIC(QHostInfoCache, globalHostInfoCache)
|
||||
|
||||
/*!
|
||||
\class QHostInfo
|
||||
|
@ -107,12 +95,9 @@ Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager)
|
|||
To retrieve the name of the local host, use the static
|
||||
QHostInfo::localHostName() function.
|
||||
|
||||
\note Since Qt 4.6.1 QHostInfo is using multiple threads for DNS lookup
|
||||
instead of one dedicated DNS thread. This improves performance,
|
||||
but also changes the order of signal emissions when using lookupHost()
|
||||
compared to previous versions of Qt.
|
||||
\note Since Qt 4.6.3 QHostInfo is using a small internal 60 second DNS cache
|
||||
\note Since 4.6.3 QHostInfo is using a small internal 60 second DNS cache
|
||||
for performance improvements.
|
||||
\note Since 4.9.0 QHostInfo is not using multiple threads for DNS lookup.
|
||||
|
||||
\sa QAbstractSocket, {http://www.rfc-editor.org/rfc/rfc3492.txt}{RFC 3492}
|
||||
*/
|
||||
|
@ -151,16 +136,11 @@ static QAtomicInt theIdCounter = QAtomicInt(1);
|
|||
int QHostInfo::lookupHost(const QString &name, QObject *receiver,
|
||||
const char *member)
|
||||
{
|
||||
#if defined QHOSTINFO_DEBUG
|
||||
#ifdef QHOSTINFO_DEBUG
|
||||
qDebug("QHostInfo::lookupHost(\"%s\", %p, %s)",
|
||||
name.toLatin1().constData(), receiver, member ? member + 1 : 0);
|
||||
#endif
|
||||
|
||||
if (!QAbstractEventDispatcher::instance(QThread::currentThread())) {
|
||||
qWarning("QHostInfo::lookupHost() called with no event dispatcher");
|
||||
return -1;
|
||||
}
|
||||
|
||||
qRegisterMetaType<QHostInfo>("QHostInfo");
|
||||
|
||||
if (!receiver)
|
||||
|
@ -169,48 +149,20 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
|
|||
int id = theIdCounter.fetchAndAddRelaxed(1); // generate unique ID
|
||||
|
||||
if (name.isEmpty()) {
|
||||
QHostInfo hostInfo(id);
|
||||
hostInfo.setError(QHostInfo::HostNotFound);
|
||||
hostInfo.setErrorString(QCoreApplication::translate("QHostInfo", "No host name given"));
|
||||
QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
|
||||
QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
|
||||
receiver, member, Qt::QueuedConnection);
|
||||
result.data()->emitResultsReady(hostInfo);
|
||||
return id;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
QHostInfoLookupManager *manager = theHostInfoLookupManager();
|
||||
|
||||
if (manager) {
|
||||
// the application is still alive
|
||||
if (manager->cache.isEnabled()) {
|
||||
// check cache first
|
||||
bool valid = false;
|
||||
QHostInfo info = manager->cache.get(name, &valid);
|
||||
if (valid) {
|
||||
info.setLookupId(id);
|
||||
QHostInfo info(id);
|
||||
info.setError(QHostInfo::HostNotFound);
|
||||
info.setErrorString(QCoreApplication::translate("QHostInfo", "No host name given"));
|
||||
QHostInfoResult result;
|
||||
QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection);
|
||||
QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member);
|
||||
result.emitResultsReady(info);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
// cache is not enabled or it was not in the cache, do normal lookup
|
||||
QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id);
|
||||
if (receiver)
|
||||
QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection);
|
||||
manager->scheduleLookup(runnable);
|
||||
}
|
||||
#else
|
||||
QHostInfo hostInfo(id);
|
||||
hostInfo.fromName(name);
|
||||
QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
|
||||
QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
|
||||
receiver, member, Qt::QueuedConnection);
|
||||
result.data()->emitResultsReady(hostInfo);
|
||||
#endif // QT_NO_THREAD
|
||||
QHostInfo info(id);
|
||||
info.fromName(name);
|
||||
QHostInfoResult result;
|
||||
QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member);
|
||||
result.emitResultsReady(info);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
@ -222,9 +174,7 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
|
|||
*/
|
||||
void QHostInfo::abortHostLookup(int id)
|
||||
{
|
||||
#ifndef QT_NO_THREAD
|
||||
theHostInfoLookupManager()->abortLookup(id);
|
||||
#endif
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -242,43 +192,18 @@ void QHostInfo::abortHostLookup(int id)
|
|||
*/
|
||||
QHostInfo QHostInfo::fromName(const QString &name)
|
||||
{
|
||||
#if defined QHOSTINFO_DEBUG
|
||||
#ifdef QHOSTINFO_DEBUG
|
||||
qDebug("QHostInfo::fromName(\"%s\")",name.toLatin1().constData());
|
||||
#endif
|
||||
|
||||
QHostInfo hostInfo = QHostInfoAgent::fromName(name);
|
||||
#ifndef QT_NO_THREAD
|
||||
QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager();
|
||||
manager->cache.put(name, hostInfo);
|
||||
#endif
|
||||
QHostInfoCache* cache = globalHostInfoCache();
|
||||
if (cache && cache->isEnabled()) {
|
||||
cache->put(name, hostInfo);
|
||||
}
|
||||
return hostInfo;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
QHostInfo QHostInfoPrivate::fromName(const QString &name, QSharedPointer<QNetworkSession> session)
|
||||
{
|
||||
#if defined QHOSTINFO_DEBUG
|
||||
qDebug("QHostInfoPrivate::fromName(\"%s\") with session %p",name.toLatin1().constData(), session.data());
|
||||
#endif
|
||||
|
||||
QHostInfo hostInfo = QHostInfoAgent::fromName(name, session);
|
||||
#ifndef QT_NO_THREAD
|
||||
QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager();
|
||||
manager->cache.put(name, hostInfo);
|
||||
#endif
|
||||
return hostInfo;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
// This function has a special implementation for symbian right now in qhostinfo_symbian.cpp but not on other OS.
|
||||
QHostInfo QHostInfoAgent::fromName(const QString &hostName, QSharedPointer<QNetworkSession>)
|
||||
{
|
||||
return QHostInfoAgent::fromName(hostName);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*!
|
||||
\enum QHostInfo::HostInfoError
|
||||
|
||||
|
@ -454,285 +379,21 @@ void QHostInfo::setErrorString(const QString &str)
|
|||
|
||||
\sa hostName()
|
||||
*/
|
||||
#ifndef QT_NO_THREAD
|
||||
QAbstractHostInfoLookupManager* QAbstractHostInfoLookupManager::globalInstance()
|
||||
{
|
||||
return theHostInfoLookupManager();
|
||||
}
|
||||
|
||||
QHostInfoRunnable::QHostInfoRunnable(QString hn, int i) : toBeLookedUp(hn), id(i)
|
||||
{
|
||||
setAutoDelete(true);
|
||||
}
|
||||
|
||||
// the QHostInfoLookupManager will at some point call this via a QThreadPool
|
||||
void QHostInfoRunnable::run()
|
||||
{
|
||||
QHostInfoLookupManager *manager = theHostInfoLookupManager();
|
||||
// check aborted
|
||||
if (manager->wasAborted(id)) {
|
||||
manager->lookupFinished(this);
|
||||
return;
|
||||
}
|
||||
|
||||
QHostInfo hostInfo;
|
||||
|
||||
// QHostInfo::lookupHost already checks the cache. However we need to check
|
||||
// it here too because it might have been cache saved by another QHostInfoRunnable
|
||||
// in the meanwhile while this QHostInfoRunnable was scheduled but not running
|
||||
if (manager->cache.isEnabled()) {
|
||||
// check the cache first
|
||||
bool valid = false;
|
||||
hostInfo = manager->cache.get(toBeLookedUp, &valid);
|
||||
if (!valid) {
|
||||
// not in cache, we need to do the lookup and store the result in the cache
|
||||
hostInfo = QHostInfoAgent::fromName(toBeLookedUp);
|
||||
manager->cache.put(toBeLookedUp, hostInfo);
|
||||
}
|
||||
} else {
|
||||
// cache is not enabled, just do the lookup and continue
|
||||
hostInfo = QHostInfoAgent::fromName(toBeLookedUp);
|
||||
}
|
||||
|
||||
// check aborted again
|
||||
if (manager->wasAborted(id)) {
|
||||
manager->lookupFinished(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// signal emission
|
||||
hostInfo.setLookupId(id);
|
||||
resultEmitter.emitResultsReady(hostInfo);
|
||||
|
||||
// now also iterate through the postponed ones
|
||||
{
|
||||
QMutexLocker locker(&manager->mutex);
|
||||
QMutableListIterator<QHostInfoRunnable*> iterator(manager->postponedLookups);
|
||||
while (iterator.hasNext()) {
|
||||
QHostInfoRunnable* postponed = iterator.next();
|
||||
if (toBeLookedUp == postponed->toBeLookedUp) {
|
||||
// we can now emit
|
||||
iterator.remove();
|
||||
hostInfo.setLookupId(postponed->id);
|
||||
postponed->resultEmitter.emitResultsReady(hostInfo);
|
||||
delete postponed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
manager->lookupFinished(this);
|
||||
|
||||
// thread goes back to QThreadPool
|
||||
}
|
||||
|
||||
QHostInfoLookupManager::QHostInfoLookupManager() : mutex(QMutex::Recursive), wasDeleted(false)
|
||||
{
|
||||
moveToThread(QCoreApplicationPrivate::mainThread());
|
||||
connect(QCoreApplication::instance(), SIGNAL(destroyed()), SLOT(waitForThreadPoolDone()), Qt::DirectConnection);
|
||||
threadPool.setMaxThreadCount(5); // do 5 DNS lookups in parallel
|
||||
}
|
||||
|
||||
QHostInfoLookupManager::~QHostInfoLookupManager()
|
||||
{
|
||||
wasDeleted = true;
|
||||
|
||||
// don't qDeleteAll currentLookups, the QThreadPool has ownership
|
||||
clear();
|
||||
}
|
||||
|
||||
void QHostInfoLookupManager::clear()
|
||||
{
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
qDeleteAll(postponedLookups);
|
||||
qDeleteAll(scheduledLookups);
|
||||
qDeleteAll(finishedLookups);
|
||||
postponedLookups.clear();
|
||||
scheduledLookups.clear();
|
||||
finishedLookups.clear();
|
||||
}
|
||||
|
||||
threadPool.waitForDone();
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
void QHostInfoLookupManager::work()
|
||||
{
|
||||
if (wasDeleted)
|
||||
return;
|
||||
|
||||
// goals of this function:
|
||||
// - launch new lookups via the thread pool
|
||||
// - make sure only one lookup per host/IP is in progress
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
|
||||
if (!finishedLookups.isEmpty()) {
|
||||
// remove ID from aborted if it is in there
|
||||
for (int i = 0; i < finishedLookups.length(); i++) {
|
||||
abortedLookups.removeAll(finishedLookups.at(i)->id);
|
||||
}
|
||||
|
||||
finishedLookups.clear();
|
||||
}
|
||||
|
||||
if (!postponedLookups.isEmpty()) {
|
||||
// try to start the postponed ones
|
||||
|
||||
QMutableListIterator<QHostInfoRunnable*> iterator(postponedLookups);
|
||||
while (iterator.hasNext()) {
|
||||
QHostInfoRunnable* postponed = iterator.next();
|
||||
|
||||
// check if none of the postponed hostnames is currently running
|
||||
bool alreadyRunning = false;
|
||||
for (int i = 0; i < currentLookups.length(); i++) {
|
||||
if (currentLookups.at(i)->toBeLookedUp == postponed->toBeLookedUp) {
|
||||
alreadyRunning = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyRunning) {
|
||||
iterator.remove();
|
||||
scheduledLookups.prepend(postponed); // prepend! we want to finish it ASAP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!scheduledLookups.isEmpty()) {
|
||||
// try to start the new ones
|
||||
QMutableListIterator<QHostInfoRunnable*> iterator(scheduledLookups);
|
||||
while (iterator.hasNext()) {
|
||||
QHostInfoRunnable *scheduled = iterator.next();
|
||||
|
||||
// check if a lookup for this host is already running, then postpone
|
||||
for (int i = 0; i < currentLookups.size(); i++) {
|
||||
if (currentLookups.at(i)->toBeLookedUp == scheduled->toBeLookedUp) {
|
||||
iterator.remove();
|
||||
postponedLookups.append(scheduled);
|
||||
scheduled = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (scheduled && currentLookups.size() < threadPool.maxThreadCount()) {
|
||||
// runnable now running in new thread, track this in currentLookups
|
||||
threadPool.start(scheduled);
|
||||
iterator.remove();
|
||||
currentLookups.append(scheduled);
|
||||
} else {
|
||||
// was postponed, continue iterating
|
||||
continue;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// called by QHostInfo
|
||||
void QHostInfoLookupManager::scheduleLookup(QHostInfoRunnable *r)
|
||||
{
|
||||
if (wasDeleted)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&this->mutex);
|
||||
scheduledLookups.enqueue(r);
|
||||
work();
|
||||
}
|
||||
|
||||
// called by QHostInfo
|
||||
void QHostInfoLookupManager::abortLookup(int id)
|
||||
{
|
||||
if (wasDeleted)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&this->mutex);
|
||||
|
||||
// is postponed? delete and return
|
||||
for (int i = 0; i < postponedLookups.length(); i++) {
|
||||
if (postponedLookups.at(i)->id == id) {
|
||||
delete postponedLookups.takeAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// is scheduled? delete and return
|
||||
for (int i = 0; i < scheduledLookups.length(); i++) {
|
||||
if (scheduledLookups.at(i)->id == id) {
|
||||
delete scheduledLookups.takeAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!abortedLookups.contains(id))
|
||||
abortedLookups.append(id);
|
||||
}
|
||||
|
||||
// called from QHostInfoRunnable
|
||||
bool QHostInfoLookupManager::wasAborted(int id)
|
||||
{
|
||||
if (wasDeleted)
|
||||
return true;
|
||||
|
||||
QMutexLocker locker(&this->mutex);
|
||||
return abortedLookups.contains(id);
|
||||
}
|
||||
|
||||
// called from QHostInfoRunnable
|
||||
void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r)
|
||||
{
|
||||
if (wasDeleted)
|
||||
return;
|
||||
|
||||
QMutexLocker locker(&this->mutex);
|
||||
currentLookups.removeOne(r);
|
||||
finishedLookups.append(r);
|
||||
work();
|
||||
}
|
||||
#endif // QT_NO_THREAD
|
||||
|
||||
// This function returns immediately when we had a result in the cache, else it will later emit a signal
|
||||
QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id)
|
||||
{
|
||||
#ifndef QT_NO_THREAD
|
||||
*valid = false;
|
||||
*id = -1;
|
||||
|
||||
// check cache
|
||||
QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager();
|
||||
if (manager && manager->cache.isEnabled()) {
|
||||
QHostInfo info = manager->cache.get(name, valid);
|
||||
if (*valid) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// was not in cache, trigger lookup
|
||||
*id = QHostInfo::lookupHost(name, receiver, member);
|
||||
|
||||
// return empty response, valid==false
|
||||
return QHostInfo();
|
||||
}
|
||||
|
||||
void qt_qhostinfo_clear_cache()
|
||||
{
|
||||
#ifndef QT_NO_THREAD
|
||||
QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager();
|
||||
if (manager) {
|
||||
manager->clear();
|
||||
QHostInfoCache* cache = globalHostInfoCache();
|
||||
if (cache) {
|
||||
cache->clear();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e)
|
||||
{
|
||||
#ifndef QT_NO_THREAD
|
||||
QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager();
|
||||
if (manager) {
|
||||
manager->cache.setEnabled(e);
|
||||
QHostInfoCache* cache = globalHostInfoCache();
|
||||
if (cache) {
|
||||
cache->setEnabled(e);
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(e);
|
||||
#endif
|
||||
}
|
||||
|
||||
// cache for 60 seconds
|
||||
|
@ -761,15 +422,14 @@ QHostInfo QHostInfoCache::get(const QString &name, bool *valid) const
|
|||
{
|
||||
*valid = false;
|
||||
QHostInfoCacheElement *element = cache.object(name);
|
||||
if (element) {
|
||||
if (element->age.elapsed() < max_age*1000)
|
||||
if (element && element->age.elapsed() < max_age*1000) {
|
||||
*valid = true;
|
||||
return element->info;
|
||||
}
|
||||
|
||||
// FIXME idea:
|
||||
// if too old but not expired, trigger a new lookup
|
||||
// to freshen our cache
|
||||
}
|
||||
|
||||
return QHostInfo();
|
||||
}
|
||||
|
|
|
@ -49,14 +49,9 @@
|
|||
#include "qcoreapplication_p.h"
|
||||
#include "QtNetwork/qhostinfo.h"
|
||||
#include "QtCore/qmutex.h"
|
||||
#include "QtCore/qwaitcondition.h"
|
||||
#include "QtCore/qobject.h"
|
||||
#include "QtCore/qpointer.h"
|
||||
#include "QtCore/qthread.h"
|
||||
#include "QtCore/qthreadpool.h"
|
||||
#include "QtCore/qrunnable.h"
|
||||
#include "QtCore/qlist.h"
|
||||
#include "QtCore/qqueue.h"
|
||||
#include <QElapsedTimer>
|
||||
#include <QCache>
|
||||
|
||||
|
@ -87,10 +82,6 @@ class QHostInfoAgent : public QObject
|
|||
Q_OBJECT
|
||||
public:
|
||||
static QHostInfo fromName(const QString &hostName);
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
static QHostInfo fromName(const QString &hostName, QSharedPointer<QNetworkSession> networkSession);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class QHostInfoPrivate
|
||||
|
@ -102,11 +93,6 @@ public:
|
|||
lookupId(0)
|
||||
{
|
||||
}
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
//not a public API yet
|
||||
static QHostInfo fromName(const QString &hostName, QSharedPointer<QNetworkSession> networkSession);
|
||||
#endif
|
||||
|
||||
QHostInfo::HostInfoError err;
|
||||
QString errorStr;
|
||||
QList<QHostAddress> addrs;
|
||||
|
@ -116,7 +102,6 @@ public:
|
|||
|
||||
// These functions are outside of the QHostInfo class and strictly internal.
|
||||
// Do NOT use them outside of QAbstractSocket.
|
||||
QHostInfo Q_NETWORK_EXPORT qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id);
|
||||
void Q_AUTOTEST_EXPORT qt_qhostinfo_clear_cache();
|
||||
void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e);
|
||||
|
||||
|
@ -142,75 +127,6 @@ private:
|
|||
QMutex mutex;
|
||||
};
|
||||
|
||||
// the following classes are used for the (normal) case: We use multiple threads to lookup DNS
|
||||
#ifndef QT_NO_THREAD
|
||||
class QHostInfoRunnable : public QRunnable
|
||||
{
|
||||
public:
|
||||
QHostInfoRunnable (QString hn, int i);
|
||||
void run();
|
||||
|
||||
QString toBeLookedUp;
|
||||
int id;
|
||||
QHostInfoResult resultEmitter;
|
||||
};
|
||||
|
||||
|
||||
class QAbstractHostInfoLookupManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~QAbstractHostInfoLookupManager() {}
|
||||
virtual void clear() = 0;
|
||||
|
||||
QHostInfoCache cache;
|
||||
|
||||
protected:
|
||||
QAbstractHostInfoLookupManager() {}
|
||||
static QAbstractHostInfoLookupManager* globalInstance();
|
||||
|
||||
};
|
||||
|
||||
class QHostInfoLookupManager : public QAbstractHostInfoLookupManager
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QHostInfoLookupManager();
|
||||
~QHostInfoLookupManager();
|
||||
|
||||
void clear();
|
||||
void work();
|
||||
|
||||
// called from QHostInfo
|
||||
void scheduleLookup(QHostInfoRunnable *r);
|
||||
void abortLookup(int id);
|
||||
|
||||
// called from QHostInfoRunnable
|
||||
void lookupFinished(QHostInfoRunnable *r);
|
||||
bool wasAborted(int id);
|
||||
|
||||
friend class QHostInfoRunnable;
|
||||
protected:
|
||||
QList<QHostInfoRunnable*> currentLookups; // in progress
|
||||
QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host
|
||||
QQueue<QHostInfoRunnable*> scheduledLookups; // not yet started
|
||||
QList<QHostInfoRunnable*> finishedLookups; // recently finished
|
||||
QList<int> abortedLookups; // ids of aborted lookups
|
||||
|
||||
QThreadPool threadPool;
|
||||
|
||||
QMutex mutex;
|
||||
|
||||
bool wasDeleted;
|
||||
|
||||
private slots:
|
||||
void waitForThreadPoolDone() { threadPool.waitForDone(); }
|
||||
};
|
||||
#endif // QT_NO_THREAD
|
||||
|
||||
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QHOSTINFO_P_H
|
||||
|
|
|
@ -1385,18 +1385,8 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint
|
|||
#endif
|
||||
} else {
|
||||
if (d->threadData->eventDispatcher) {
|
||||
// this internal API for QHostInfo either immediately gives us the desired
|
||||
// QHostInfo from cache or later calls the _q_startConnecting slot.
|
||||
bool immediateResultValid = false;
|
||||
QHostInfo hostInfo = qt_qhostinfo_lookup(hostName,
|
||||
this,
|
||||
SLOT(_q_startConnecting(QHostInfo)),
|
||||
&immediateResultValid,
|
||||
&d->hostLookupId);
|
||||
if (immediateResultValid) {
|
||||
d->hostLookupId = -1;
|
||||
d->_q_startConnecting(hostInfo);
|
||||
}
|
||||
d->_q_startConnecting(QHostInfo::fromName(hostName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1740,14 +1730,6 @@ bool QAbstractSocket::waitForConnected(int msecs)
|
|||
#endif
|
||||
QHostInfo::abortHostLookup(d->hostLookupId);
|
||||
d->hostLookupId = -1;
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
QSharedPointer<QNetworkSession> networkSession;
|
||||
QVariant v(property("_q_networksession"));
|
||||
if (v.isValid()) {
|
||||
networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(v);
|
||||
d->_q_startConnecting(QHostInfoPrivate::fromName(d->hostName, networkSession));
|
||||
} else
|
||||
#endif
|
||||
d->_q_startConnecting(QHostInfo::fromName(d->hostName));
|
||||
}
|
||||
if (state() == UnconnectedState)
|
||||
|
|
|
@ -105,12 +105,6 @@ private slots:
|
|||
void multipleDifferentLookups_data();
|
||||
void multipleDifferentLookups();
|
||||
|
||||
void cache();
|
||||
|
||||
void abortHostLookup();
|
||||
#ifndef QT_NO_THREAD
|
||||
void abortHostLookupInDifferentThread();
|
||||
#endif
|
||||
protected slots:
|
||||
void resultsReady(const QHostInfo &);
|
||||
|
||||
|
@ -539,49 +533,6 @@ void tst_QHostInfo::multipleDifferentLookups()
|
|||
QCOMPARE(lookupsDoneCounter, repeats*COUNT);
|
||||
}
|
||||
|
||||
void tst_QHostInfo::cache()
|
||||
{
|
||||
QFETCH_GLOBAL(bool, cache);
|
||||
if (!cache)
|
||||
return; // test makes only sense when cache enabled
|
||||
|
||||
// reset slot counter
|
||||
lookupsDoneCounter = 0;
|
||||
|
||||
// lookup once, wait in event loop, result should not come directly.
|
||||
bool valid = true;
|
||||
int id = -1;
|
||||
QHostInfo result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
QVERIFY(valid == false);
|
||||
QVERIFY(result.addresses().isEmpty());
|
||||
|
||||
// loopkup second time, result should come directly
|
||||
valid = false;
|
||||
result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
|
||||
#if defined(Q_OS_LINUX)
|
||||
if (valid != true)
|
||||
QEXPECT_FAIL("", "QTBUG-28079", Continue);
|
||||
#endif
|
||||
QVERIFY(valid == true);
|
||||
QVERIFY(!result.addresses().isEmpty());
|
||||
|
||||
// clear the cache
|
||||
qt_qhostinfo_clear_cache();
|
||||
|
||||
// lookup third time, result should not come directly.
|
||||
valid = true;
|
||||
result = qt_qhostinfo_lookup("localhost", this, SLOT(resultsReady(QHostInfo)), &valid, &id);
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
QVERIFY(valid == false);
|
||||
QVERIFY(result.addresses().isEmpty());
|
||||
|
||||
// the slot should have been called 2 times.
|
||||
QCOMPARE(lookupsDoneCounter, 2);
|
||||
}
|
||||
|
||||
void tst_QHostInfo::resultsReady(const QHostInfo &hi)
|
||||
{
|
||||
lookupDone = true;
|
||||
|
@ -590,59 +541,6 @@ void tst_QHostInfo::resultsReady(const QHostInfo &hi)
|
|||
QMetaObject::invokeMethod(&QTestEventLoop::instance(), "exitLoop", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void tst_QHostInfo::abortHostLookup()
|
||||
{
|
||||
//reset counter
|
||||
lookupsDoneCounter = 0;
|
||||
bool valid = false;
|
||||
int id = -1;
|
||||
QHostInfo result = qt_qhostinfo_lookup("a-single" TEST_DOMAIN, this, SLOT(resultsReady(QHostInfo)), &valid, &id);
|
||||
QVERIFY(!valid);
|
||||
//it is assumed that the DNS request/response in the backend is slower than it takes to call abort
|
||||
QHostInfo::abortHostLookup(id);
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
#if defined(Q_OS_LINUX)
|
||||
if (lookupsDoneCounter != 0)
|
||||
QEXPECT_FAIL("", "QTBUG-28079", Continue);
|
||||
#endif
|
||||
QCOMPARE(lookupsDoneCounter, 0);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_THREAD
|
||||
class LookupAborter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public slots:
|
||||
void abort()
|
||||
{
|
||||
QHostInfo::abortHostLookup(id);
|
||||
QThread::currentThread()->quit();
|
||||
}
|
||||
public:
|
||||
int id;
|
||||
};
|
||||
|
||||
void tst_QHostInfo::abortHostLookupInDifferentThread()
|
||||
{
|
||||
//reset counter
|
||||
lookupsDoneCounter = 0;
|
||||
bool valid = false;
|
||||
int id = -1;
|
||||
QHostInfo result = qt_qhostinfo_lookup("a-single" TEST_DOMAIN, this, SLOT(resultsReady(QHostInfo)), &valid, &id);
|
||||
QVERIFY(!valid);
|
||||
QThread thread;
|
||||
LookupAborter aborter;
|
||||
aborter.id = id;
|
||||
aborter.moveToThread(&thread);
|
||||
connect(&thread, SIGNAL(started()), &aborter, SLOT(abort()));
|
||||
//it is assumed that the DNS request/response in the backend is slower than it takes to schedule the thread and call abort
|
||||
thread.start();
|
||||
QVERIFY(thread.wait(5000));
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
QCOMPARE(lookupsDoneCounter, 0);
|
||||
}
|
||||
#endif // QT_NO_THREAD
|
||||
|
||||
QTEST_MAIN(tst_QHostInfo)
|
||||
|
||||
#include "moc_tst_qhostinfo.cpp"
|
||||
|
|
Loading…
Add table
Reference in a new issue