Update ResourceCache to allow multiple downloads on the same resource

This commit is contained in:
Ryan Huffman 2015-08-19 12:11:47 -07:00
parent 51d4cf84da
commit 4827d326f4
3 changed files with 99 additions and 82 deletions

View file

@ -95,7 +95,6 @@ void Sound::downloadFinished(const QByteArray& data) {
}
_isReady = true;
_request->deleteLater();
}
void Sound::downSample(const QByteArray& rawAudioByteArray) {

View file

@ -154,12 +154,13 @@ void ResourceCache::clearUnusedResource() {
void ResourceCache::attemptRequest(Resource* resource) {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
if (_requestLimit <= 0) {
qDebug() << "REQUEST LIMIT REACHED, queueing: " << resource->getURL();
// wait until a slot becomes available
sharedItems->_pendingRequests.append(resource);
return;
}
// if (_requestLimit <= 0) {
// qDebug() << "REQUEST LIMIT REACHED (" << _requestLimit << "), queueing: " << resource->getURL();
// // wait until a slot becomes available
// sharedItems->_pendingRequests.append(resource);
// return;
// }
qDebug() << "-- Decreasing limit for : " << resource->getURL();
_requestLimit--;
sharedItems->_loadingRequests.append(resource);
resource->makeRequest();
@ -169,6 +170,7 @@ void ResourceCache::requestCompleted(Resource* resource) {
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
sharedItems->_loadingRequests.removeOne(resource);
qDebug() << "++ Increasing limit after finished: " << resource->getURL();
_requestLimit++;
// look for the highest priority pending request
@ -198,13 +200,14 @@ int ResourceCache::_requestLimit = DEFAULT_REQUEST_LIMIT;
Resource::Resource(const QUrl& url, bool delayLoad) :
_url(url),
_activeUrl(url),
_request(nullptr) {
init();
// start loading immediately unless instructed otherwise
if (!(_startedLoading || delayLoad)) {
QTimer::singleShot(1, this, &Resource::attemptRequest);
// QTimer::singleShot(1, this, &Resource::attemptRequest);
//attemptRequest();
}
}
@ -264,11 +267,8 @@ void Resource::refresh() {
}
if (_request) {
_request->disconnect(this);
// _requestTimer->disconnect(this);
_request->deleteLater();
_request = nullptr;
// _requestTimer->deleteLater();
// _requestTimer = nullptr;
ResourceCache::requestCompleted(this);
}
@ -302,6 +302,7 @@ void Resource::init() {
_failedToLoad = false;
_loaded = false;
_attempts = 0;
_activeUrl = _url;
if (_url.isEmpty()) {
_startedLoading = _loaded = true;
@ -317,6 +318,7 @@ void Resource::attemptRequest() {
}
void Resource::finishedLoading(bool success) {
qDebug() << "Finished loading: " << _url;
if (success) {
_loaded = true;
emit loaded();
@ -349,15 +351,6 @@ void Resource::reinsert() {
// // downloadFinished(reply);
// }
//
// void Resource::handleReplyError() {
// handleReplyError(_reply->error(), qDebug() << _reply->errorString());
// }
//
// void Resource::handleReplyTimeout() {
// handleReplyError(QNetworkReply::TimeoutError, qDebug() << "Timed out loading" << _reply->url() <<
// "received" << _bytesReceived << "total" << _bytesTotal);
// }
//
void Resource::maybeRefresh() {
if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
@ -382,31 +375,30 @@ void Resource::maybeRefresh() {
}
}
// #include "AssetManager.h"
void Resource::makeRequest() {
auto request = ResourceManager::createResourceRequest(this, _url);
_request = request;
QString u = _activeUrl.path();
QString uu = _url.path();
Q_ASSERT(!_request);
_request = ResourceManager::createResourceRequest(this, _activeUrl);
if (!_request) {
qDebug() << "Failed to get request for " << _url;
ResourceCache::requestCompleted(this);
finishedLoading(false);
return;
}
qDebug() << "Starting request for: " << _url;
connect(request, &ResourceRequest::finished, this, &Resource::handleReplyFinished);
connect(_request, &ResourceRequest::finished, this, &Resource::handleReplyFinished);
// connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64)));
// connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError()));
// connect(_reply, SIGNAL(finished()), SLOT(handleReplyFinished()));
// AssetManager::getAsset(_url, [this](AssetRequestUpdateType type, QByteArray data) {
// if (type == AssetRequestUpdateType::COMPLETE) {
// downloadFinished(data);
// } else {
// handleReplyError(QNetworkReply::TimeoutError, qDebug());
// }
// });
//
request->send();
_bytesReceived = _bytesTotal = 0;
_request->send();
// if (_reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool()) {
// // If the file as been updated since it was cached, refresh it
@ -435,63 +427,88 @@ void Resource::makeRequest() {
// }
// }
// }
// _replyTimer = new QTimer(this);
// connect(_replyTimer, SIGNAL(timeout()), SLOT(handleReplyTimeout()));
// _replyTimer->setSingleShot(true);
// _replyTimer->start(REPLY_TIMEOUT_MS);
_bytesReceived = _bytesTotal = 0;
}
// void Resource::handleReplyError(QNetworkReply::NetworkError error, QDebug debug) {
// _reply->disconnect(this);
// _replyTimer->disconnect(this);
// _reply->deleteLater();
// _reply = nullptr;
// _replyTimer->deleteLater();
// _replyTimer = nullptr;
// ResourceCache::requestCompleted(this);
//
// // retry for certain types of failures
// switch (error) {
// case QNetworkReply::RemoteHostClosedError:
// case QNetworkReply::TimeoutError:
// case QNetworkReply::TemporaryNetworkFailureError:
// case QNetworkReply::ProxyConnectionClosedError:
// case QNetworkReply::ProxyTimeoutError:
// case QNetworkReply::UnknownNetworkError:
// case QNetworkReply::UnknownProxyError:
// case QNetworkReply::UnknownContentError:
// case QNetworkReply::ProtocolFailure: {
// // retry with increasing delays
// const int MAX_ATTEMPTS = 8;
// const int BASE_DELAY_MS = 1000;
// if (++_attempts < MAX_ATTEMPTS) {
// QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(attemptRequest()));
// debug << "-- retrying...";
// return;
// }
// // fall through to final failure
// }
// default:
// finishedLoading(false);
// break;
// }
// void Resource::handleReplyError(ResourceRequest::Result result, QDebug debug) {
//
// // // retry for certain types of failures
// // switch (error) {
// // case QNetworkReply::RemoteHostClosedError:
// // case QNetworkReply::TimeoutError:
// // case QNetworkReply::TemporaryNetworkFailureError:
// // case QNetworkReply::ProxyConnectionClosedError:
// // case QNetworkReply::ProxyTimeoutError:
// // case QNetworkReply::UnknownNetworkError:
// // case QNetworkReply::UnknownProxyError:
// // case QNetworkReply::UnknownContentError:
// // case QNetworkReply::ProtocolFailure: {
// // // retry with increasing delays
// // const int MAX_ATTEMPTS = 8;
// // const int BASE_DELAY_MS = 1000;
// // if (++_attempts < MAX_ATTEMPTS) {
// // QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(nttemptRequest()));
// // debug << "-- retrying...";
// // return;
// // }
// // // fall through to final failure
// // }
// // default:
// // finishedLoading(false);
// // break;
// // }
// }
//
void Resource::handleReplyFinished() {
// _request->disconnect(this);
// _request->deleteLater();
// _request = nullptr;
QString u = _url.path();
Q_ASSERT(_request);
if (_request->getResult() == ResourceRequest::SUCCESS) {
auto result = _request->getResult();
if (result == ResourceRequest::SUCCESS) {
_data = _request->moveData();
qDebug() << "Reqeust finsihed for " << _url << ", " << _activeUrl;
_request->disconnect(this);
_request->deleteLater();
_request = nullptr;
ResourceCache::requestCompleted(this);
downloadFinished(_data);
} else {
_request->disconnect(this);
_request->deleteLater();
_request = nullptr;
if (result == ResourceRequest::Result::TIMEOUT) {
qDebug() << "Timed out loading" << _url <<
"received" << _bytesReceived << "total" << _bytesTotal;
} else {
qDebug() << "Error loading " << _url;
}
bool retry = false;
switch (result) {
case ResourceRequest::Result::TIMEOUT:
case ResourceRequest::Result::ERROR: {
// retry with increasing delays
const int MAX_ATTEMPTS = 8;
const int BASE_DELAY_MS = 1000;
if (++_attempts < MAX_ATTEMPTS) {
QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(attemptRequest()));
retry = true;
break;
}
// fall through to final failure
}
default:
finishedLoading(false);
break;
}
if (!retry) {
ResourceCache::requestCompleted(this);
}
}
ResourceCache::requestCompleted(this);
}
uint qHash(const QPointer<QObject>& value, uint seed) {

View file

@ -199,8 +199,7 @@ protected:
virtual void reinsert();
QUrl _url;
ResourceRequest* _request = nullptr;
//QNetworkRequest _request;
QUrl _activeUrl;
bool _startedLoading = false;
bool _failedToLoad = false;
bool _loaded = false;
@ -211,19 +210,21 @@ protected:
private slots:
// void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
// void handleReplyError();
void handleReplyFinished();
// void handleReplyError();
// void handleReplyTimeout();
private:
void setLRUKey(int lruKey) { _lruKey = lruKey; }
void makeRequest();
void retry();
void handleReplyError(QNetworkReply::NetworkError error, QDebug debug);
// void handleReplyError(ResourceRequest::Result result, QDebug debug);
friend class ResourceCache;
ResourceRequest* _request = nullptr;
int _lruKey = 0;
QTimer* _replyTimer = nullptr;
qint64 _bytesReceived = 0;