mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 04:18:12 +02:00
Update ResourceCache to use ResourceRequest
This commit is contained in:
parent
fc9cd836ce
commit
ccc0000fd0
2 changed files with 157 additions and 126 deletions
|
@ -155,6 +155,7 @@ void ResourceCache::clearUnusedResource() {
|
||||||
void ResourceCache::attemptRequest(Resource* resource) {
|
void ResourceCache::attemptRequest(Resource* resource) {
|
||||||
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
auto sharedItems = DependencyManager::get<ResourceCacheSharedItems>();
|
||||||
if (_requestLimit <= 0) {
|
if (_requestLimit <= 0) {
|
||||||
|
qDebug() << "REQUEST LIMIT REACHED, queueing: " << resource->getURL();
|
||||||
// wait until a slot becomes available
|
// wait until a slot becomes available
|
||||||
sharedItems->_pendingRequests.append(resource);
|
sharedItems->_pendingRequests.append(resource);
|
||||||
return;
|
return;
|
||||||
|
@ -187,6 +188,7 @@ void ResourceCache::requestCompleted(Resource* resource) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (highestIndex >= 0) {
|
if (highestIndex >= 0) {
|
||||||
|
qDebug() << "trying to attempt a pending request";
|
||||||
attemptRequest(sharedItems->_pendingRequests.takeAt(highestIndex));
|
attemptRequest(sharedItems->_pendingRequests.takeAt(highestIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,24 +198,22 @@ int ResourceCache::_requestLimit = DEFAULT_REQUEST_LIMIT;
|
||||||
|
|
||||||
Resource::Resource(const QUrl& url, bool delayLoad) :
|
Resource::Resource(const QUrl& url, bool delayLoad) :
|
||||||
_url(url),
|
_url(url),
|
||||||
_request(url) {
|
_request(nullptr) {
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
_request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
|
||||||
_request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
|
||||||
|
|
||||||
// start loading immediately unless instructed otherwise
|
// start loading immediately unless instructed otherwise
|
||||||
if (!(_startedLoading || delayLoad)) {
|
if (!(_startedLoading || delayLoad)) {
|
||||||
attemptRequest();
|
QTimer::singleShot(1, this, &Resource::attemptRequest);
|
||||||
|
//attemptRequest();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource::~Resource() {
|
Resource::~Resource() {
|
||||||
if (_reply) {
|
if (_request) {
|
||||||
ResourceCache::requestCompleted(this);
|
ResourceCache::requestCompleted(this);
|
||||||
delete _reply;
|
_request->deleteLater();
|
||||||
_reply = nullptr;
|
_request = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,21 +259,20 @@ float Resource::getLoadPriority() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::refresh() {
|
void Resource::refresh() {
|
||||||
if (_reply && !(_loaded || _failedToLoad)) {
|
if (_request && !(_loaded || _failedToLoad)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_reply) {
|
if (_request) {
|
||||||
|
_request->disconnect(this);
|
||||||
|
// _requestTimer->disconnect(this);
|
||||||
|
_request->deleteLater();
|
||||||
|
_request = nullptr;
|
||||||
|
// _requestTimer->deleteLater();
|
||||||
|
// _requestTimer = nullptr;
|
||||||
ResourceCache::requestCompleted(this);
|
ResourceCache::requestCompleted(this);
|
||||||
_reply->disconnect(this);
|
|
||||||
_replyTimer->disconnect(this);
|
|
||||||
_reply->deleteLater();
|
|
||||||
_reply = nullptr;
|
|
||||||
_replyTimer->deleteLater();
|
|
||||||
_replyTimer = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init();
|
init();
|
||||||
_request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
|
|
||||||
ensureLoading();
|
ensureLoading();
|
||||||
emit onRefresh();
|
emit onRefresh();
|
||||||
}
|
}
|
||||||
|
@ -331,34 +330,34 @@ void Resource::reinsert() {
|
||||||
_cache->_resources.insert(_url, _self);
|
_cache->_resources.insert(_url, _self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int REPLY_TIMEOUT_MS = 5000;
|
// static const int REPLY_TIMEOUT_MS = 5000;
|
||||||
void Resource::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
// void Resource::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
||||||
if (!_reply->isFinished()) {
|
// if (!_reply->isFinished()) {
|
||||||
_bytesReceived = bytesReceived;
|
// _bytesReceived = bytesReceived;
|
||||||
_bytesTotal = bytesTotal;
|
// _bytesTotal = bytesTotal;
|
||||||
_replyTimer->start(REPLY_TIMEOUT_MS);
|
// _replyTimer->start(REPLY_TIMEOUT_MS);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
_reply->disconnect(this);
|
// _reply->disconnect(this);
|
||||||
_replyTimer->disconnect(this);
|
// _replyTimer->disconnect(this);
|
||||||
QNetworkReply* reply = _reply;
|
// QNetworkReply* reply = _reply;
|
||||||
_reply = nullptr;
|
// _reply = nullptr;
|
||||||
_replyTimer->deleteLater();
|
// _replyTimer->deleteLater();
|
||||||
_replyTimer = nullptr;
|
// _replyTimer = nullptr;
|
||||||
ResourceCache::requestCompleted(this);
|
// ResourceCache::requestCompleted(this);
|
||||||
|
//
|
||||||
downloadFinished(reply);
|
// // downloadFinished(reply);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
void Resource::handleReplyError() {
|
// void Resource::handleReplyError() {
|
||||||
handleReplyError(_reply->error(), qDebug() << _reply->errorString());
|
// handleReplyError(_reply->error(), qDebug() << _reply->errorString());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
void Resource::handleReplyTimeout() {
|
// void Resource::handleReplyTimeout() {
|
||||||
handleReplyError(QNetworkReply::TimeoutError, qDebug() << "Timed out loading" << _reply->url() <<
|
// handleReplyError(QNetworkReply::TimeoutError, qDebug() << "Timed out loading" << _reply->url() <<
|
||||||
"received" << _bytesReceived << "total" << _bytesTotal);
|
// "received" << _bytesReceived << "total" << _bytesTotal);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
void Resource::maybeRefresh() {
|
void Resource::maybeRefresh() {
|
||||||
if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) {
|
if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) {
|
||||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||||
|
@ -383,87 +382,116 @@ void Resource::maybeRefresh() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #include "AssetManager.h"
|
||||||
void Resource::makeRequest() {
|
void Resource::makeRequest() {
|
||||||
_reply = NetworkAccessManager::getInstance().get(_request);
|
auto request = ResourceManager::createResourceRequest(this, _url);
|
||||||
|
_request = request;
|
||||||
connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64)));
|
if (!_request) {
|
||||||
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError()));
|
qDebug() << "Failed to get request for " << _url;
|
||||||
connect(_reply, SIGNAL(finished()), SLOT(handleReplyFinished()));
|
return;
|
||||||
|
|
||||||
if (_reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool()) {
|
|
||||||
// If the file as been updated since it was cached, refresh it
|
|
||||||
QNetworkRequest request(_request);
|
|
||||||
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
|
|
||||||
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
|
|
||||||
QNetworkReply* reply = NetworkAccessManager::getInstance().head(request);
|
|
||||||
connect(reply, &QNetworkReply::finished, this, &Resource::maybeRefresh);
|
|
||||||
} else {
|
|
||||||
if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) {
|
|
||||||
QNetworkCacheMetaData metaData = NetworkAccessManager::getInstance().cache()->metaData(_url);
|
|
||||||
bool needUpdate = false;
|
|
||||||
if (metaData.expirationDate().isNull() || metaData.expirationDate() <= QDateTime::currentDateTime()) {
|
|
||||||
// If the expiration date is NULL or in the past,
|
|
||||||
// put one far enough away that it won't be an issue.
|
|
||||||
metaData.setExpirationDate(QDateTime::currentDateTime().addYears(100));
|
|
||||||
needUpdate = true;
|
|
||||||
}
|
|
||||||
if (metaData.lastModified().isNull()) {
|
|
||||||
// If the lastModified date is NULL, set it to now.
|
|
||||||
metaData.setLastModified(QDateTime::currentDateTime());
|
|
||||||
needUpdate = true;
|
|
||||||
}
|
|
||||||
if (needUpdate) {
|
|
||||||
NetworkAccessManager::getInstance().cache()->updateMetaData(metaData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_replyTimer = new QTimer(this);
|
qDebug() << "Starting request for: " << _url;
|
||||||
connect(_replyTimer, SIGNAL(timeout()), SLOT(handleReplyTimeout()));
|
|
||||||
_replyTimer->setSingleShot(true);
|
connect(request, &ResourceRequest::finished, this, &Resource::handleReplyFinished);
|
||||||
_replyTimer->start(REPLY_TIMEOUT_MS);
|
// 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();
|
||||||
|
|
||||||
|
// if (_reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool()) {
|
||||||
|
// // If the file as been updated since it was cached, refresh it
|
||||||
|
// QNetworkRequest request(_request);
|
||||||
|
// request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
|
||||||
|
// request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false);
|
||||||
|
// QNetworkReply* reply = NetworkAccessManager::getInstance().head(request);
|
||||||
|
// connect(reply, &QNetworkReply::finished, this, &Resource::maybeRefresh);
|
||||||
|
// } else {
|
||||||
|
// if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) {
|
||||||
|
// QNetworkCacheMetaData metaData = NetworkAccessManager::getInstance().cache()->metaData(_url);
|
||||||
|
// bool needUpdate = false;
|
||||||
|
// if (metaData.expirationDate().isNull() || metaData.expirationDate() <= QDateTime::currentDateTime()) {
|
||||||
|
// // If the expiration date is NULL or in the past,
|
||||||
|
// // put one far enough away that it won't be an issue.
|
||||||
|
// metaData.setExpirationDate(QDateTime::currentDateTime().addYears(100));
|
||||||
|
// needUpdate = true;
|
||||||
|
// }
|
||||||
|
// if (metaData.lastModified().isNull()) {
|
||||||
|
// // If the lastModified date is NULL, set it to now.
|
||||||
|
// metaData.setLastModified(QDateTime::currentDateTime());
|
||||||
|
// needUpdate = true;
|
||||||
|
// }
|
||||||
|
// if (needUpdate) {
|
||||||
|
// NetworkAccessManager::getInstance().cache()->updateMetaData(metaData);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _replyTimer = new QTimer(this);
|
||||||
|
// connect(_replyTimer, SIGNAL(timeout()), SLOT(handleReplyTimeout()));
|
||||||
|
// _replyTimer->setSingleShot(true);
|
||||||
|
// _replyTimer->start(REPLY_TIMEOUT_MS);
|
||||||
_bytesReceived = _bytesTotal = 0;
|
_bytesReceived = _bytesTotal = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Resource::handleReplyError(QNetworkReply::NetworkError error, QDebug debug) {
|
// void Resource::handleReplyError(QNetworkReply::NetworkError error, QDebug debug) {
|
||||||
_reply->disconnect(this);
|
// _reply->disconnect(this);
|
||||||
_replyTimer->disconnect(this);
|
// _replyTimer->disconnect(this);
|
||||||
_reply->deleteLater();
|
// _reply->deleteLater();
|
||||||
_reply = nullptr;
|
// _reply = nullptr;
|
||||||
_replyTimer->deleteLater();
|
// _replyTimer->deleteLater();
|
||||||
_replyTimer = nullptr;
|
// _replyTimer = nullptr;
|
||||||
ResourceCache::requestCompleted(this);
|
// ResourceCache::requestCompleted(this);
|
||||||
|
//
|
||||||
// retry for certain types of failures
|
// // retry for certain types of failures
|
||||||
switch (error) {
|
// switch (error) {
|
||||||
case QNetworkReply::RemoteHostClosedError:
|
// case QNetworkReply::RemoteHostClosedError:
|
||||||
case QNetworkReply::TimeoutError:
|
// case QNetworkReply::TimeoutError:
|
||||||
case QNetworkReply::TemporaryNetworkFailureError:
|
// case QNetworkReply::TemporaryNetworkFailureError:
|
||||||
case QNetworkReply::ProxyConnectionClosedError:
|
// case QNetworkReply::ProxyConnectionClosedError:
|
||||||
case QNetworkReply::ProxyTimeoutError:
|
// case QNetworkReply::ProxyTimeoutError:
|
||||||
case QNetworkReply::UnknownNetworkError:
|
// case QNetworkReply::UnknownNetworkError:
|
||||||
case QNetworkReply::UnknownProxyError:
|
// case QNetworkReply::UnknownProxyError:
|
||||||
case QNetworkReply::UnknownContentError:
|
// case QNetworkReply::UnknownContentError:
|
||||||
case QNetworkReply::ProtocolFailure: {
|
// case QNetworkReply::ProtocolFailure: {
|
||||||
// retry with increasing delays
|
// // retry with increasing delays
|
||||||
const int MAX_ATTEMPTS = 8;
|
// const int MAX_ATTEMPTS = 8;
|
||||||
const int BASE_DELAY_MS = 1000;
|
// const int BASE_DELAY_MS = 1000;
|
||||||
if (++_attempts < MAX_ATTEMPTS) {
|
// if (++_attempts < MAX_ATTEMPTS) {
|
||||||
QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(attemptRequest()));
|
// QTimer::singleShot(BASE_DELAY_MS * (int)pow(2.0, _attempts), this, SLOT(attemptRequest()));
|
||||||
debug << "-- retrying...";
|
// debug << "-- retrying...";
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
// fall through to final failure
|
// // fall through to final failure
|
||||||
}
|
// }
|
||||||
default:
|
// default:
|
||||||
finishedLoading(false);
|
// finishedLoading(false);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
void Resource::handleReplyFinished() {
|
void Resource::handleReplyFinished() {
|
||||||
qCDebug(networking) << "Got finished without download progress/error?" << _url;
|
// _request->disconnect(this);
|
||||||
handleDownloadProgress(0, 0);
|
// _request->deleteLater();
|
||||||
|
// _request = nullptr;
|
||||||
|
Q_ASSERT(_request);
|
||||||
|
if (_request->getResult() == ResourceRequest::SUCCESS) {
|
||||||
|
_data = _request->moveData();
|
||||||
|
_request->disconnect(this);
|
||||||
|
_request->deleteLater();
|
||||||
|
_request = nullptr;
|
||||||
|
downloadFinished(_data);
|
||||||
|
}
|
||||||
|
ResourceCache::requestCompleted(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint qHash(const QPointer<QObject>& value, uint seed) {
|
uint qHash(const QPointer<QObject>& value, uint seed) {
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
|
|
||||||
|
#include "ResourceManager.h"
|
||||||
|
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
|
@ -102,7 +104,7 @@ protected:
|
||||||
void reserveUnusedResource(qint64 resourceSize);
|
void reserveUnusedResource(qint64 resourceSize);
|
||||||
void clearUnusedResource();
|
void clearUnusedResource();
|
||||||
|
|
||||||
static void attemptRequest(Resource* resource);
|
Q_INVOKABLE static void attemptRequest(Resource* resource);
|
||||||
static void requestCompleted(Resource* resource);
|
static void requestCompleted(Resource* resource);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -188,7 +190,7 @@ protected:
|
||||||
virtual void init();
|
virtual void init();
|
||||||
|
|
||||||
/// Called when the download has finished. The recipient should delete the reply when done with it.
|
/// Called when the download has finished. The recipient should delete the reply when done with it.
|
||||||
virtual void downloadFinished(QNetworkReply* reply) = 0;
|
virtual void downloadFinished(const QByteArray& data) = 0;
|
||||||
|
|
||||||
/// Should be called by subclasses when all the loading that will be done has been done.
|
/// Should be called by subclasses when all the loading that will be done has been done.
|
||||||
Q_INVOKABLE void finishedLoading(bool success);
|
Q_INVOKABLE void finishedLoading(bool success);
|
||||||
|
@ -197,19 +199,21 @@ protected:
|
||||||
virtual void reinsert();
|
virtual void reinsert();
|
||||||
|
|
||||||
QUrl _url;
|
QUrl _url;
|
||||||
QNetworkRequest _request;
|
ResourceRequest* _request = nullptr;
|
||||||
|
//QNetworkRequest _request;
|
||||||
bool _startedLoading = false;
|
bool _startedLoading = false;
|
||||||
bool _failedToLoad = false;
|
bool _failedToLoad = false;
|
||||||
bool _loaded = false;
|
bool _loaded = false;
|
||||||
QHash<QPointer<QObject>, float> _loadPriorities;
|
QHash<QPointer<QObject>, float> _loadPriorities;
|
||||||
QWeakPointer<Resource> _self;
|
QWeakPointer<Resource> _self;
|
||||||
QPointer<ResourceCache> _cache;
|
QPointer<ResourceCache> _cache;
|
||||||
|
QByteArray _data;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
// void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||||
void handleReplyError();
|
// void handleReplyError();
|
||||||
void handleReplyFinished();
|
void handleReplyFinished();
|
||||||
void handleReplyTimeout();
|
// void handleReplyTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setLRUKey(int lruKey) { _lruKey = lruKey; }
|
void setLRUKey(int lruKey) { _lruKey = lruKey; }
|
||||||
|
@ -221,7 +225,6 @@ private:
|
||||||
friend class ResourceCache;
|
friend class ResourceCache;
|
||||||
|
|
||||||
int _lruKey = 0;
|
int _lruKey = 0;
|
||||||
QNetworkReply* _reply = nullptr;
|
|
||||||
QTimer* _replyTimer = nullptr;
|
QTimer* _replyTimer = nullptr;
|
||||||
qint64 _bytesReceived = 0;
|
qint64 _bytesReceived = 0;
|
||||||
qint64 _bytesTotal = 0;
|
qint64 _bytesTotal = 0;
|
||||||
|
|
Loading…
Reference in a new issue