mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 06:43:41 +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) {
|
||||
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;
|
||||
|
@ -187,6 +188,7 @@ void ResourceCache::requestCompleted(Resource* resource) {
|
|||
i++;
|
||||
}
|
||||
if (highestIndex >= 0) {
|
||||
qDebug() << "trying to attempt a pending request";
|
||||
attemptRequest(sharedItems->_pendingRequests.takeAt(highestIndex));
|
||||
}
|
||||
}
|
||||
|
@ -196,24 +198,22 @@ int ResourceCache::_requestLimit = DEFAULT_REQUEST_LIMIT;
|
|||
|
||||
Resource::Resource(const QUrl& url, bool delayLoad) :
|
||||
_url(url),
|
||||
_request(url) {
|
||||
_request(nullptr) {
|
||||
|
||||
init();
|
||||
|
||||
_request.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
_request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
||||
|
||||
// start loading immediately unless instructed otherwise
|
||||
if (!(_startedLoading || delayLoad)) {
|
||||
attemptRequest();
|
||||
QTimer::singleShot(1, this, &Resource::attemptRequest);
|
||||
//attemptRequest();
|
||||
}
|
||||
}
|
||||
|
||||
Resource::~Resource() {
|
||||
if (_reply) {
|
||||
if (_request) {
|
||||
ResourceCache::requestCompleted(this);
|
||||
delete _reply;
|
||||
_reply = nullptr;
|
||||
_request->deleteLater();
|
||||
_request = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,21 +259,20 @@ float Resource::getLoadPriority() {
|
|||
}
|
||||
|
||||
void Resource::refresh() {
|
||||
if (_reply && !(_loaded || _failedToLoad)) {
|
||||
if (_request && !(_loaded || _failedToLoad)) {
|
||||
return;
|
||||
}
|
||||
if (_reply) {
|
||||
if (_request) {
|
||||
_request->disconnect(this);
|
||||
// _requestTimer->disconnect(this);
|
||||
_request->deleteLater();
|
||||
_request = nullptr;
|
||||
// _requestTimer->deleteLater();
|
||||
// _requestTimer = nullptr;
|
||||
ResourceCache::requestCompleted(this);
|
||||
_reply->disconnect(this);
|
||||
_replyTimer->disconnect(this);
|
||||
_reply->deleteLater();
|
||||
_reply = nullptr;
|
||||
_replyTimer->deleteLater();
|
||||
_replyTimer = nullptr;
|
||||
}
|
||||
|
||||
init();
|
||||
_request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
|
||||
ensureLoading();
|
||||
emit onRefresh();
|
||||
}
|
||||
|
@ -331,34 +330,34 @@ void Resource::reinsert() {
|
|||
_cache->_resources.insert(_url, _self);
|
||||
}
|
||||
|
||||
static const int REPLY_TIMEOUT_MS = 5000;
|
||||
void Resource::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
if (!_reply->isFinished()) {
|
||||
_bytesReceived = bytesReceived;
|
||||
_bytesTotal = bytesTotal;
|
||||
_replyTimer->start(REPLY_TIMEOUT_MS);
|
||||
return;
|
||||
}
|
||||
_reply->disconnect(this);
|
||||
_replyTimer->disconnect(this);
|
||||
QNetworkReply* reply = _reply;
|
||||
_reply = nullptr;
|
||||
_replyTimer->deleteLater();
|
||||
_replyTimer = nullptr;
|
||||
ResourceCache::requestCompleted(this);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// static const int REPLY_TIMEOUT_MS = 5000;
|
||||
// void Resource::handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
// if (!_reply->isFinished()) {
|
||||
// _bytesReceived = bytesReceived;
|
||||
// _bytesTotal = bytesTotal;
|
||||
// _replyTimer->start(REPLY_TIMEOUT_MS);
|
||||
// return;
|
||||
// }
|
||||
// _reply->disconnect(this);
|
||||
// _replyTimer->disconnect(this);
|
||||
// QNetworkReply* reply = _reply;
|
||||
// _reply = nullptr;
|
||||
// _replyTimer->deleteLater();
|
||||
// _replyTimer = nullptr;
|
||||
// ResourceCache::requestCompleted(this);
|
||||
//
|
||||
// // 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());
|
||||
|
@ -383,87 +382,116 @@ void Resource::maybeRefresh() {
|
|||
}
|
||||
}
|
||||
|
||||
// #include "AssetManager.h"
|
||||
void Resource::makeRequest() {
|
||||
_reply = NetworkAccessManager::getInstance().get(_request);
|
||||
|
||||
connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64)));
|
||||
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError()));
|
||||
connect(_reply, SIGNAL(finished()), SLOT(handleReplyFinished()));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
auto request = ResourceManager::createResourceRequest(this, _url);
|
||||
_request = request;
|
||||
if (!_request) {
|
||||
qDebug() << "Failed to get request for " << _url;
|
||||
return;
|
||||
}
|
||||
|
||||
_replyTimer = new QTimer(this);
|
||||
connect(_replyTimer, SIGNAL(timeout()), SLOT(handleReplyTimeout()));
|
||||
_replyTimer->setSingleShot(true);
|
||||
_replyTimer->start(REPLY_TIMEOUT_MS);
|
||||
qDebug() << "Starting request for: " << _url;
|
||||
|
||||
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();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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(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::handleReplyFinished() {
|
||||
qCDebug(networking) << "Got finished without download progress/error?" << _url;
|
||||
handleDownloadProgress(0, 0);
|
||||
// _request->disconnect(this);
|
||||
// _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) {
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#include <DependencyManager.h>
|
||||
|
||||
#include "ResourceManager.h"
|
||||
|
||||
class QNetworkReply;
|
||||
class QTimer;
|
||||
|
||||
|
@ -102,7 +104,7 @@ protected:
|
|||
void reserveUnusedResource(qint64 resourceSize);
|
||||
void clearUnusedResource();
|
||||
|
||||
static void attemptRequest(Resource* resource);
|
||||
Q_INVOKABLE static void attemptRequest(Resource* resource);
|
||||
static void requestCompleted(Resource* resource);
|
||||
|
||||
private:
|
||||
|
@ -188,7 +190,7 @@ protected:
|
|||
virtual void init();
|
||||
|
||||
/// 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.
|
||||
Q_INVOKABLE void finishedLoading(bool success);
|
||||
|
@ -197,19 +199,21 @@ protected:
|
|||
virtual void reinsert();
|
||||
|
||||
QUrl _url;
|
||||
QNetworkRequest _request;
|
||||
ResourceRequest* _request = nullptr;
|
||||
//QNetworkRequest _request;
|
||||
bool _startedLoading = false;
|
||||
bool _failedToLoad = false;
|
||||
bool _loaded = false;
|
||||
QHash<QPointer<QObject>, float> _loadPriorities;
|
||||
QWeakPointer<Resource> _self;
|
||||
QPointer<ResourceCache> _cache;
|
||||
QByteArray _data;
|
||||
|
||||
private slots:
|
||||
void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void handleReplyError();
|
||||
// void handleDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
// void handleReplyError();
|
||||
void handleReplyFinished();
|
||||
void handleReplyTimeout();
|
||||
// void handleReplyTimeout();
|
||||
|
||||
private:
|
||||
void setLRUKey(int lruKey) { _lruKey = lruKey; }
|
||||
|
@ -221,7 +225,6 @@ private:
|
|||
friend class ResourceCache;
|
||||
|
||||
int _lruKey = 0;
|
||||
QNetworkReply* _reply = nullptr;
|
||||
QTimer* _replyTimer = nullptr;
|
||||
qint64 _bytesReceived = 0;
|
||||
qint64 _bytesTotal = 0;
|
||||
|
|
Loading…
Reference in a new issue