summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorMartin Petersson <Martin.Petersson@nokia.com>2012-05-11 09:42:52 (GMT)
committerQt by Nokia <qt-info@nokia.com>2012-05-13 21:55:26 (GMT)
commita93b7025c71f8c4f81ba3b516a65ee41e6ef419c (patch)
treea7216357c9429417378a91a53ba25f607b71794b /src/network
parentfb6c3e4f31dd0943d8751c986f7112dccd604211 (diff)
downloadQt-a93b7025c71f8c4f81ba3b516a65ee41e6ef419c.zip
Qt-a93b7025c71f8c4f81ba3b516a65ee41e6ef419c.tar.gz
Qt-a93b7025c71f8c4f81ba3b516a65ee41e6ef419c.tar.bz2
QNetworkReply::setReadBufferSize fix for threaded http
Added the setReadBufferSize functionallity again by limiting the amount that the delegate read from the channel. Each time that data is fetched from the reply buffer, we communicate back to the thread so that more data can be fetched. Task-number: QTBUG-25327 Change-Id: I08a246f4e7fbfdb8d58f4c5982ed0c9fa474f560 Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qhttpnetworkreply.cpp28
-rw-r--r--src/network/access/qhttpnetworkreply_p.h4
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp50
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h4
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp12
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h2
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp14
-rw-r--r--src/network/access/qnetworkaccesshttpbackend_p.h4
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp11
9 files changed, 123 insertions, 6 deletions
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index acd4b55..e52aa80 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -201,6 +201,18 @@ QByteArray QHttpNetworkReply::readAll()
return d->responseData.readAll();
}
+QByteArray QHttpNetworkReply::read(qint64 amount)
+{
+ Q_D(QHttpNetworkReply);
+ return d->responseData.read(amount);
+}
+
+qint64 QHttpNetworkReply::sizeNextBlock()
+{
+ Q_D(QHttpNetworkReply);
+ return d->responseData.sizeNextBlock();
+}
+
void QHttpNetworkReply::setDownstreamLimited(bool dsl)
{
Q_D(QHttpNetworkReply);
@@ -208,6 +220,12 @@ void QHttpNetworkReply::setDownstreamLimited(bool dsl)
d->connection->d_func()->readMoreLater(this);
}
+void QHttpNetworkReply::setReadBufferSize(qint64 size)
+{
+ Q_D(QHttpNetworkReply);
+ d->readBufferMaxSize = size;
+}
+
bool QHttpNetworkReply::supportsUserProvidedDownloadBuffer()
{
Q_D(QHttpNetworkReply);
@@ -253,7 +271,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
connectionCloseEnabled(true),
forceConnectionCloseEnabled(false),
lastChunkRead(false),
- currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false),
+ currentChunkSize(0), currentChunkRead(0), readBufferMaxSize(0), connection(0), initInflate(false),
autoDecompress(false), responseData(), requestIsPrepared(false)
,pipeliningUsed(false), downstreamLimited(false)
,userProvidedDownloadBuffer(0)
@@ -699,6 +717,8 @@ qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QByteData
{
qint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead);
+ if (readBufferMaxSize)
+ toBeRead = qMin(toBeRead, readBufferMaxSize);
QByteArray bd;
bd.resize(toBeRead);
qint64 haveRead = socket->read(bd.data(), toBeRead);
@@ -746,6 +766,8 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QAbstractSocket *socket, QByte
Q_ASSERT(out);
int toBeRead = qMin<qint64>(128*1024, qMin<qint64>(size, socket->bytesAvailable()));
+ if (readBufferMaxSize)
+ toBeRead = qMin<qint64>(toBeRead, readBufferMaxSize);
while (toBeRead > 0) {
QByteArray byteData;
@@ -772,6 +794,10 @@ qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QAbstractSocket *socket, Q
{
qint64 bytes = 0;
while (socket->bytesAvailable()) {
+
+ if (readBufferMaxSize && (bytes > readBufferMaxSize))
+ break;
+
if (!lastChunkRead && currentChunkRead >= currentChunkSize) {
// For the first chunk and when we're done with a chunk
currentChunkSize = 0;
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index 92b29ce..032dccb 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -128,7 +128,10 @@ public:
bool readAnyAvailable() const;
QByteArray readAny();
QByteArray readAll();
+ QByteArray read(qint64 amount);
+ qint64 sizeNextBlock();
void setDownstreamLimited(bool t);
+ void setReadBufferSize(qint64 size);
bool supportsUserProvidedDownloadBuffer();
void setUserProvidedDownloadBuffer(char*);
@@ -236,6 +239,7 @@ public:
bool lastChunkRead;
qint64 currentChunkSize;
qint64 currentChunkRead;
+ qint64 readBufferMaxSize;
QPointer<QHttpNetworkConnection> connection;
QPointer<QHttpNetworkConnectionChannel> connectionChannel;
bool initInflate;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 698ca2d..d120373 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -194,6 +194,8 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) :
QObject(parent)
, ssl(false)
, downloadBufferMaximumSize(0)
+ , readBufferMaxSize(0)
+ , bytesEmitted(0)
, pendingDownloadData(0)
, pendingDownloadProgress(0)
, synchronous(false)
@@ -349,15 +351,57 @@ void QHttpThreadDelegate::abortRequest()
}
}
+void QHttpThreadDelegate::readBufferSizeChanged(qint64 size)
+{
+#ifdef QHTTPTHREADDELEGATE_DEBUG
+ qDebug() << "QHttpThreadDelegate::readBufferSizeChanged() size " << size;
+#endif
+ if (httpReply) {
+ httpReply->setDownstreamLimited(true);
+ httpReply->setReadBufferSize(size);
+ readBufferMaxSize = size;
+ }
+}
+
+void QHttpThreadDelegate::readBufferFreed(qint64 size)
+{
+ if (readBufferMaxSize) {
+ bytesEmitted -= size;
+
+ QMetaObject::invokeMethod(this, "readyReadSlot", Qt::QueuedConnection);
+ }
+}
+
void QHttpThreadDelegate::readyReadSlot()
{
// Don't do in zerocopy case
if (!downloadBuffer.isNull())
return;
- while (httpReply->readAnyAvailable()) {
- pendingDownloadData->fetchAndAddRelease(1);
- emit downloadData(httpReply->readAny());
+ if (readBufferMaxSize) {
+ if (bytesEmitted < readBufferMaxSize) {
+ qint64 sizeEmitted = 0;
+ while (httpReply->readAnyAvailable() && (sizeEmitted < (readBufferMaxSize-bytesEmitted))) {
+ if (httpReply->sizeNextBlock() > (readBufferMaxSize-bytesEmitted)) {
+ sizeEmitted = readBufferMaxSize-bytesEmitted;
+ bytesEmitted += sizeEmitted;
+ pendingDownloadData->fetchAndAddRelease(1);
+ emit downloadData(httpReply->read(sizeEmitted));
+ } else {
+ sizeEmitted = httpReply->sizeNextBlock();
+ bytesEmitted += sizeEmitted;
+ pendingDownloadData->fetchAndAddRelease(1);
+ emit downloadData(httpReply->readAny());
+ }
+ }
+ } else {
+ // We need to wait until we empty data from the read buffer in the reply.
+ }
+ } else {
+ while (httpReply->readAnyAvailable()) {
+ pendingDownloadData->fetchAndAddRelease(1);
+ emit downloadData(httpReply->readAny());
+ }
}
}
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index e43f38a..c105ca2 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -93,6 +93,8 @@ public:
#endif
QHttpNetworkRequest httpRequest;
qint64 downloadBufferMaximumSize;
+ qint64 readBufferMaxSize;
+ qint64 bytesEmitted;
// From backend, modified by us for signal compression
QSharedPointer<QAtomicInt> pendingDownloadData;
QSharedPointer<QAtomicInt> pendingDownloadProgress;
@@ -145,6 +147,8 @@ public slots:
// This are called via QueuedConnection from user thread
void startRequest();
void abortRequest();
+ void readBufferSizeChanged(qint64 size);
+ void readBufferFreed(qint64 size);
// This is called with a BlockingQueuedConnection from user thread
void startRequestSynchronously();
protected slots:
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 2869232..db2243c 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -164,6 +164,18 @@ void QNetworkAccessBackend::setDownstreamLimited(bool b)
// do nothing
}
+void QNetworkAccessBackend::setReadBufferSize(qint64 size)
+{
+ Q_UNUSED(size);
+ // do nothing
+}
+
+void QNetworkAccessBackend::emitReadBufferFreed(qint64 size)
+{
+ Q_UNUSED(size);
+ // do nothing
+}
+
void QNetworkAccessBackend::copyFinished(QIODevice *)
{
// do nothing
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index f9563da..cc3df80 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -116,6 +116,8 @@ public:
// slot-like:
virtual void downstreamReadyWrite();
virtual void setDownstreamLimited(bool b);
+ virtual void setReadBufferSize(qint64 size);
+ virtual void emitReadBufferFreed(qint64 size);
virtual void copyFinished(QIODevice *);
virtual void ignoreSslErrors();
virtual void ignoreSslErrors(const QList<QSslError> &errors);
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index db2b83e..0b2af93 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -598,6 +598,10 @@ void QNetworkAccessHttpBackend::postRequest()
connect(this, SIGNAL(startHttpRequest()), delegate, SLOT(startRequest()));
connect(this, SIGNAL(abortHttpRequest()), delegate, SLOT(abortRequest()));
+ // To throttle the connection.
+ QObject::connect(this, SIGNAL(readBufferSizeChanged(qint64)), delegate, SLOT(readBufferSizeChanged(qint64)));
+ QObject::connect(this, SIGNAL(readBufferFreed(qint64)), delegate, SLOT(readBufferFreed(qint64)));
+
if (uploadByteDevice) {
QNonContiguousByteDeviceThreadForwardImpl *forwardUploadDevice =
new QNonContiguousByteDeviceThreadForwardImpl(uploadByteDevice->atEnd(), uploadByteDevice->size());
@@ -705,6 +709,16 @@ void QNetworkAccessHttpBackend::setDownstreamLimited(bool b)
// The task to fix this is QTBUG-15065
}
+void QNetworkAccessHttpBackend::setReadBufferSize(qint64 size)
+{
+ emit readBufferSizeChanged(size);
+}
+
+void QNetworkAccessHttpBackend::emitReadBufferFreed(qint64 size)
+{
+ emit readBufferFreed(size);
+}
+
void QNetworkAccessHttpBackend::replyDownloadData(QByteArray d)
{
int pendingSignals = (int)pendingDownloadDataEmissions->fetchAndAddAcquire(-1) - 1;
diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h
index 273b7ee..c5c2073 100644
--- a/src/network/access/qnetworkaccesshttpbackend_p.h
+++ b/src/network/access/qnetworkaccesshttpbackend_p.h
@@ -84,6 +84,8 @@ public:
virtual void downstreamReadyWrite();
virtual void setDownstreamLimited(bool b);
+ virtual void setReadBufferSize(qint64 size);
+ virtual void emitReadBufferFreed(qint64 size);
virtual void copyFinished(QIODevice *);
#ifndef QT_NO_OPENSSL
@@ -105,6 +107,8 @@ signals:
// To HTTP thread:
void startHttpRequest();
void abortHttpRequest();
+ void readBufferSizeChanged(qint64 size);
+ void readBufferFreed(qint64 size);
void startHttpRequestSynchronously();
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index a94bb0f..b0e81e9 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -946,8 +946,10 @@ void QNetworkReplyImpl::setReadBufferSize(qint64 size)
QNetworkReply::setReadBufferSize(size);
- if (d->backend)
+ if (d->backend) {
d->backend->setDownstreamLimited(d->readBufferMaxSize > 0);
+ d->backend->setReadBufferSize(size);
+ }
}
#ifndef QT_NO_OPENSSL
@@ -1009,11 +1011,16 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen)
if (maxlen == 1) {
// optimization for getChar()
*data = d->readBuffer.getChar();
+ if (d->backend && readBufferSize())
+ d->backend->emitReadBufferFreed(1);
return 1;
}
maxlen = qMin<qint64>(maxlen, d->readBuffer.byteAmount());
- return d->readBuffer.read(data, maxlen);
+ qint64 bytesRead = d->readBuffer.read(data, maxlen);
+ if (d->backend && readBufferSize())
+ d->backend->emitReadBufferFreed(bytesRead);
+ return bytesRead;
}
/*!