summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-03-07 01:46:24 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-03-07 01:46:24 (GMT)
commite56ae7fb7b269afe36a3bd2f4de0c10f8c2a6924 (patch)
treef130e76140457cf8071193278acd783d898c54fb /src/network
parentb20ef0ade0aec89b969bd0ae7f754c680e390c67 (diff)
parent66733e95351f0088fd206a9215bde9d14510bc1e (diff)
downloadQt-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.cpp6
-rw-r--r--src/network/kernel/qhostinfo.cpp161
-rw-r--r--src/network/kernel/qhostinfo_p.h32
-rw-r--r--src/network/socket/qabstractsocket.cpp26
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)