summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2009-04-03 14:51:21 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2009-04-06 07:55:17 (GMT)
commitb11659ba9ea4532583398f6e539e78ed79a0c600 (patch)
tree20d6a95a1f626aaa3cc144140f39cbdf160d283b
parent020ced4994bace0ed7f494bec8905afa959f76ed (diff)
downloadQt-b11659ba9ea4532583398f6e539e78ed79a0c600.zip
Qt-b11659ba9ea4532583398f6e539e78ed79a0c600.tar.gz
Qt-b11659ba9ea4532583398f6e539e78ed79a0c600.tar.bz2
Fix QNetworkReply's automatic pushing of a cache when the cache is
more than 64k. This issue was found by Warwick: the copyReadyRead() slot is called only once as a result of readyRead(), but since there's no more data to be received (the source QIODevice is a QBuffer), we'll never get a readyRead() again. So, if we don't have a limited buffer size, we should read everything. This applies to QFile as well. The side-effect is that we cause the entire QFile to be loaded to memory, so if you had a 2 GB cache entry, you'll probably run out of memory. Future optimisations: - don't memcpy the data from a QBuffer into another buffer - find a way to avoid loading the entire contents of the file (probably not possible with the default QNetworkDiskCache since that may compress the data, so we won't know the size and thus can't fake finished()) Reviewed-by: Warwick Allison
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp44
1 files changed, 27 insertions, 17 deletions
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index eaa572f..79c3d1a 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -131,27 +131,37 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead()
if (!copyDevice && !q->isOpen())
return;
- qint64 bytesToRead = nextDownstreamBlockSize();
- if (bytesToRead == 0)
- // we'll be called again, eventually
- return;
+ forever {
+ qint64 bytesToRead = nextDownstreamBlockSize();
+ if (bytesToRead == 0)
+ // we'll be called again, eventually
+ break;
- bytesToRead = qBound<qint64>(1, bytesToRead, copyDevice->bytesAvailable());
- char *ptr = readBuffer.reserve(bytesToRead);
- qint64 bytesActuallyRead = copyDevice->read(ptr, bytesToRead);
- if (bytesActuallyRead == -1) {
- readBuffer.chop(bytesToRead);
- backendNotify(NotifyCopyFinished);
- return;
- }
+ bytesToRead = qBound<qint64>(1, bytesToRead, copyDevice->bytesAvailable());
+ char *ptr = readBuffer.reserve(bytesToRead);
+ qint64 bytesActuallyRead = copyDevice->read(ptr, bytesToRead);
+ if (bytesActuallyRead == -1) {
+ readBuffer.chop(bytesToRead);
+ backendNotify(NotifyCopyFinished);
+ return;
+ }
- if (bytesActuallyRead != bytesToRead)
- readBuffer.chop(bytesToRead - bytesActuallyRead);
+ if (bytesActuallyRead != bytesToRead)
+ readBuffer.chop(bytesToRead - bytesActuallyRead);
- if (!copyDevice->isSequential() && copyDevice->atEnd())
- backendNotify(NotifyCopyFinished);
+ if (!copyDevice->isSequential() && copyDevice->atEnd()) {
+ backendNotify(NotifyCopyFinished);
+ break;
+ }
+
+ bytesDownloaded += bytesActuallyRead;
+ }
+
+ if (bytesDownloaded == lastBytesDownloaded) {
+ // we didn't read anything
+ return;
+ }
- bytesDownloaded += bytesActuallyRead;
lastBytesDownloaded = bytesDownloaded;
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
emit q->downloadProgress(bytesDownloaded,