diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-03-07 01:46:24 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-03-07 01:46:24 (GMT) |
commit | e56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924 (patch) | |
tree | f130e76140457cf8071193278acd783d898c54fb /src/network | |
parent | b20ef0ade0aec89b969bd0ae7f754c680e390c67 (diff) | |
parent | 66733e95351f0088fd206a9215bde9d14510bc1e (diff) | |
download | Qt-e56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924.zip Qt-e56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924.tar.gz Qt-e56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924.tar.bz2 |
Merge branch 'qt-4.7-from-4.6' of scm.dev.nokia.troll.no:qt/qt-integration into 4.7-integration
* 'qt-4.7-from-4.6' of scm.dev.nokia.troll.no:qt/qt-integration: (123 commits)
Added missing tests to tests/auto/*.pro
Compile with DirectFB version >= 1.2.0 && < 1.2.9
QDirectFBPaintEngine optimization
Add some warnings when using DISABLE/WARN in DFB
Fix build with Mesa 7.8's EGL implementatioon
Reset the byte order in the iconv codec after using it.
fix "using namespace" recursion crash
Fix for QTBUG-6659 Parent window accepts pointer events wrongly
If no IAP defined force IAP dialog
Fixed key mappings on X11
QDom: prevent infinite loop when cloning a DTD
Compile fix for Windows Mobile and OpenGLES2
QPrintPreviewDialog number of pages is partially blocked from view in OSX
QS60Style ignores widget palette when drawing highlighted widget text
Fix for QTBUG-8762 QApplication::setGraphicsSystem("raster") crashes.
Fixed crash at application exit when QProcess was used in Symbian
QMessageBox is not stretched to screen width if the content is narrow
Wrong dirty region after row selection in right-to-left mode in QTableView
Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit/qtwebkit-4.6 ( f3110d2f94c825477afac054ed448e45d47f5670 )
Tab to space fixes to qdilaog.cpp
...
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 6 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo.cpp | 161 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo_p.h | 32 | ||||
-rw-r--r-- | src/network/socket/qabstractsocket.cpp | 26 |
4 files changed, 211 insertions, 14 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index e92b2f3..806452c 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -681,7 +681,11 @@ void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests() connection->d_func()->requeueRequest(alreadyPipelinedRequests.at(i)); alreadyPipelinedRequests.clear(); - QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + // only run when the QHttpNetworkConnection is not currently being destructed, e.g. + // this function is called from _q_disconnected which is called because + // of ~QHttpNetworkConnectionPrivate + if (qobject_cast<QHttpNetworkConnection*>(connection)) + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } void QHttpNetworkConnectionChannel::eatWhitespace() diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 93f6d13..4800e9d 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -112,6 +112,13 @@ 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 + for performance improvements. + \sa QAbstractSocket, {http://www.rfc-editor.org/rfc/rfc3492.txt}{RFC 3492} */ @@ -181,9 +188,26 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, receiver, member, Qt::QueuedConnection); result.data()->emitResultsReady(hostInfo); #else - QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id); - QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); - theHostInfoLookupManager()->scheduleLookup(runnable); + 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); + QHostInfoResult result; + QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + 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); + QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection); + manager->scheduleLookup(runnable); + } #endif return id; @@ -418,14 +442,24 @@ void QHostInfoRunnable::run() return; } - // check cache - // FIXME - - // if not in cache: OS lookup - QHostInfo hostInfo = QHostInfoAgent::fromName(toBeLookedUp); - - // save to cache - // FIXME + 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)) { @@ -451,6 +485,11 @@ QHostInfoLookupManager::QHostInfoLookupManager() : mutex(QMutex::Recursive), was QHostInfoLookupManager::~QHostInfoLookupManager() { wasDeleted = true; + + // don't qDeleteAll currentLookups, the QThreadPool has ownership + qDeleteAll(postponedLookups); + qDeleteAll(scheduledLookups); + qDeleteAll(finishedLookups); } void QHostInfoLookupManager::work() @@ -570,6 +609,106 @@ void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r) work(); } +// This function returns immediatly 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) +{ + *valid = false; + *id = -1; + + // check cache + QHostInfoLookupManager* manager = theHostInfoLookupManager(); + if (manager && manager->cache.isEnabled()) { + QHostInfo info = manager->cache.get(name, valid); + if (*valid) { + return info; + } + } + + // was not in cache, trigger lookup + *id = QHostInfo::lookupHost(name, receiver, member); + + // return empty response, valid==false + return QHostInfo(); +} + +void qt_qhostinfo_clear_cache() +{ + QHostInfoLookupManager* manager = theHostInfoLookupManager(); + if (manager) { + manager->cache.clear(); + } +} + +void Q_NETWORK_EXPORT qt_qhostinfo_enable_cache(bool e) +{ + QHostInfoLookupManager* manager = theHostInfoLookupManager(); + if (manager) { + manager->cache.setEnabled(e); + } +} + +// cache for 60 seconds +// cache 64 items +QHostInfoCache::QHostInfoCache() : max_age(60), enabled(true), cache(64) +{ +#ifdef QT_QHOSTINFO_CACHE_DISABLED_BY_DEFAULT + enabled = false; +#endif +} + +bool QHostInfoCache::isEnabled() +{ + return enabled; +} + +// this function is currently only used for the auto tests +// and not usable by public API +void QHostInfoCache::setEnabled(bool e) +{ + enabled = e; +} + + +QHostInfo QHostInfoCache::get(const QString &name, bool *valid) +{ + QMutexLocker locker(&this->mutex); + + *valid = false; + if (cache.contains(name)) { + QHostInfoCacheElement *element = cache.object(name); + if (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(); +} + +void QHostInfoCache::put(const QString &name, const QHostInfo &info) +{ + // if the lookup failed, don't cache + if (info.error() != QHostInfo::NoError) + return; + + QHostInfoCacheElement* element = new QHostInfoCacheElement(); + element->info = info; + element->age = QTime(); + element->age.start(); + + QMutexLocker locker(&this->mutex); + cache.insert(name, element); // cache will take ownership +} + +void QHostInfoCache::clear() +{ + QMutexLocker locker(&this->mutex); + cache.clear(); +} + #endif // QT_NO_THREAD QT_END_NAMESPACE diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index d6aa287..2b26b07 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -68,6 +68,8 @@ #include "QtCore/qrunnable.h" #include "QtCore/qlist.h" #include "QtCore/qqueue.h" +#include <QTime> +#include <QCache> #endif QT_BEGIN_NAMESPACE @@ -111,6 +113,34 @@ public: }; #ifndef QT_NO_THREAD +// 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_NETWORK_EXPORT qt_qhostinfo_clear_cache(); +void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e); + +class QHostInfoCache +{ +public: + QHostInfoCache(); + const int max_age; // seconds + + QHostInfo get(const QString &name, bool *valid); + void put(const QString &name, const QHostInfo &info); + void clear(); + + bool isEnabled(); + void setEnabled(bool e); +private: + bool enabled; + struct QHostInfoCacheElement { + QHostInfo info; + QTime age; + }; + QCache<QString,QHostInfoCacheElement> cache; + QMutex mutex; +}; + // the following classes are used for the (normal) case: We use multiple threads to lookup DNS class QHostInfoRunnable : public QRunnable @@ -141,6 +171,7 @@ public: void lookupFinished(QHostInfoRunnable *r); bool wasAborted(int id); + QHostInfoCache cache; protected: QList<QHostInfoRunnable*> currentLookups; // in progress QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host @@ -154,6 +185,7 @@ protected: bool wasDeleted; }; + #endif QT_END_NAMESPACE diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 275c436..95721ee 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -172,6 +172,10 @@ This signal is emitted after connectToHost() has been called and the host lookup has succeeded. + \note Since Qt 4.6.3 QAbstractSocket may emit hostFound() + directly from the connectToHost() call since a DNS result could have been + cached. + \sa connected() */ @@ -181,6 +185,10 @@ This signal is emitted after connectToHost() has been called and a connection has been successfully established. + \note On some operating systems the connected() signal may + be directly emitted from the connectToHost() call for connections + to the localhost. + \sa connectToHost(), disconnected() */ @@ -354,6 +362,8 @@ #include "qabstractsocket.h" #include "qabstractsocket_p.h" +#include "private/qhostinfo_p.h" + #include <qabstracteventdispatcher.h> #include <qdatetime.h> #include <qhostaddress.h> @@ -1369,8 +1379,20 @@ void QAbstractSocket::connectToHostImplementation(const QString &hostName, quint return; #endif } else { - if (d->threadData->eventDispatcher) - d->hostLookupId = QHostInfo::lookupHost(hostName, this, SLOT(_q_startConnecting(QHostInfo))); + if (d->threadData->eventDispatcher) { + // this internal API for QHostInfo either immediatly 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); + } + } } #if defined(QABSTRACTSOCKET_DEBUG) |