14 #ifndef hifi_ResourceCache_h
15 #define hifi_ResourceCache_h
20 #include <QtCore/QHash>
21 #include <QtCore/QList>
22 #include <QtCore/QObject>
23 #include <QtCore/QPointer>
24 #include <QtCore/QSharedPointer>
25 #include <QtCore/QUrl>
26 #include <QtCore/QWeakPointer>
27 #include <QtCore/QReadWriteLock>
28 #include <QtCore/QQueue>
30 #include <QtNetwork/QNetworkReply>
31 #include <QtNetwork/QNetworkRequest>
33 #include <DependencyManager.h>
35 #include "ResourceManager.h"
37 Q_DECLARE_METATYPE(
size_t)
44 static const qint64 BYTES_PER_MEGABYTES = 1024 * 1024;
45 static const qint64 BYTES_PER_GIGABYTES = 1024 * BYTES_PER_MEGABYTES;
46 static const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES;
51 static const qint64 DEFAULT_UNUSED_MAX_SIZE = 100 * BYTES_PER_MEGABYTES;
53 static const qint64 DEFAULT_UNUSED_MAX_SIZE = 1024 * BYTES_PER_MEGABYTES;
55 static const qint64 MIN_UNUSED_MAX_SIZE = 0;
56 static const qint64 MAX_UNUSED_MAX_SIZE = MAXIMUM_CACHE_SIZE;
62 class ResourceCacheSharedItems :
public Dependency {
65 using Mutex = std::recursive_mutex;
66 using Lock = std::unique_lock<Mutex>;
69 bool appendRequest(QWeakPointer<Resource> newRequest);
70 void removeRequest(QWeakPointer<Resource> doneRequest);
71 void setRequestLimit(uint32_t limit);
72 uint32_t getRequestLimit()
const;
73 QList<QSharedPointer<Resource>> getPendingRequests()
const;
74 QSharedPointer<Resource> getHighestPendingRequest();
75 uint32_t getPendingRequestsCount()
const;
76 QList<QSharedPointer<Resource>> getLoadingRequests()
const;
77 uint32_t getLoadingRequestsCount()
const;
81 ResourceCacheSharedItems() =
default;
84 QList<QWeakPointer<Resource>> _pendingRequests;
85 QList<QWeakPointer<Resource>> _loadingRequests;
86 const uint32_t DEFAULT_REQUEST_LIMIT = 10;
87 uint32_t _requestLimit { DEFAULT_REQUEST_LIMIT };
110 Q_PROPERTY(QUrl url READ getURL)
111 Q_PROPERTY(
int state READ getState NOTIFY stateChanged)
140 Q_INVOKABLE
void release();
142 const QUrl& getURL()
const {
return _url; }
143 int getState()
const {
return (
int)_state; }
144 const QSharedPointer<Resource>& getResource()
const {
return _resource; }
146 bool isInScript()
const;
147 void setInScript(
bool isInScript);
158 void progressChanged(uint64_t bytesReceived, uint64_t bytesTotal);
166 void stateChanged(
int state);
169 void setState(State state) { _state = state; emit stateChanged(_state); }
172 void loadingChanged();
173 void loadedChanged();
174 void finished(
bool success);
177 void disconnectHelper();
182 QSharedPointer<Resource> _resource;
184 QMetaObject::Connection _progressConnection;
185 QMetaObject::Connection _loadingConnection;
186 QMetaObject::Connection _loadedConnection;
187 QMetaObject::Connection _finishedConnection;
190 State _state{ QUEUED };
199 Q_PROPERTY(
size_t numTotal READ getNumTotalResources NOTIFY dirty)
200 Q_PROPERTY(
size_t numCached READ getNumCachedResources NOTIFY dirty)
201 Q_PROPERTY(
size_t sizeTotal READ getSizeTotalResources NOTIFY dirty)
202 Q_PROPERTY(
size_t sizeCached READ getSizeCachedResources NOTIFY dirty)
206 size_t getNumTotalResources()
const {
return _numTotalResources; }
207 size_t getSizeTotalResources()
const {
return _totalResourcesSize; }
208 size_t getNumCachedResources()
const {
return _numUnusedResources; }
209 size_t getSizeCachedResources()
const {
return _unusedResourcesSize; }
211 Q_INVOKABLE QVariantList getResourceList();
213 static void setRequestLimit(uint32_t limit);
214 static uint32_t getRequestLimit() {
return DependencyManager::get<ResourceCacheSharedItems>()->getRequestLimit(); }
216 void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize);
217 qint64 getUnusedResourceCacheSize()
const {
return _unusedResourcesMaxSize; }
219 static QList<QSharedPointer<Resource>> getLoadingRequests();
220 static uint32_t getPendingRequestCount();
221 static uint32_t getLoadingRequestCount();
227 void clearUnusedResources();
235 void updateTotalSize(
const qint64& deltaSize);
248 QSharedPointer<Resource>
getResource(
const QUrl& url,
const QUrl& fallback = QUrl()) {
return getResource(url, fallback,
nullptr, std::numeric_limits<size_t>::max()); }
249 QSharedPointer<Resource>
getResource(
const QUrl& url,
const QUrl& fallback,
void* extra,
size_t extraHash);
252 void clearATPAssets();
260 Q_INVOKABLE
ScriptableResource* prefetch(
const QUrl& url) {
return prefetch(url,
nullptr, std::numeric_limits<size_t>::max()); }
264 virtual QSharedPointer<Resource> createResourceCopy(
const QSharedPointer<Resource>& resource) = 0;
266 void addUnusedResource(
const QSharedPointer<Resource>& resource);
267 void removeUnusedResource(
const QSharedPointer<Resource>& resource);
272 static void requestCompleted(QWeakPointer<Resource> resource);
273 static bool attemptHighestPriorityRequest();
279 void reserveUnusedResource(qint64 resourceSize);
280 void removeResource(
const QUrl& url,
size_t extraHash, qint64 size = 0);
282 void resetTotalResourceCounter();
283 void resetUnusedResourceCounter();
284 void resetResourceCounters();
287 QHash<QUrl, QMultiHash<size_t, QWeakPointer<Resource>>> _resources;
288 QReadWriteLock _resourcesLock { QReadWriteLock::Recursive };
291 std::atomic<size_t> _numTotalResources { 0 };
292 std::atomic<qint64> _totalResourcesSize { 0 };
295 QMap<int, QSharedPointer<Resource>> _unusedResources;
296 QReadWriteLock _unusedResourcesLock { QReadWriteLock::Recursive };
297 qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE;
299 std::atomic<size_t> _numUnusedResources { 0 };
300 std::atomic<qint64> _unusedResourcesSize { 0 };
316 Q_PROPERTY(
size_t numTotal READ getNumTotalResources NOTIFY dirty)
317 Q_PROPERTY(
size_t numCached READ getNumCachedResources NOTIFY dirty)
318 Q_PROPERTY(
size_t sizeTotal READ getSizeTotalResources NOTIFY dirty)
319 Q_PROPERTY(
size_t sizeCached READ getSizeCachedResources NOTIFY dirty)
327 Q_PROPERTY(
size_t numGlobalQueriesPending READ getNumGlobalQueriesPending NOTIFY dirty)
328 Q_PROPERTY(
size_t numGlobalQueriesLoading READ getNumGlobalQueriesLoading NOTIFY dirty)
343 Q_INVOKABLE QVariantList getResourceList();
350 Q_INVOKABLE
void updateTotalSize(
const qint64& deltaSize);
382 Q_INVOKABLE
ScriptableResource* prefetch(
const QUrl& url) {
return prefetch(url,
nullptr, std::numeric_limits<size_t>::max()); }
385 Q_INVOKABLE
ScriptableResource* prefetch(
const QUrl& url,
void* extra,
size_t extraHash);
397 QSharedPointer<ResourceCache> _resourceCache;
399 size_t getNumTotalResources()
const {
return _resourceCache->getNumTotalResources(); }
400 size_t getSizeTotalResources()
const {
return _resourceCache->getSizeTotalResources(); }
401 size_t getNumCachedResources()
const {
return _resourceCache->getNumCachedResources(); }
402 size_t getSizeCachedResources()
const {
return _resourceCache->getSizeCachedResources(); }
404 size_t getNumGlobalQueriesPending()
const {
return ResourceCache::getPendingRequestCount(); }
405 size_t getNumGlobalQueriesLoading()
const {
return ResourceCache::getLoadingRequestCount(); }
413 Resource() : QObject(), _loaded(
true) {}
418 virtual QString getType()
const {
return "Resource"; }
427 virtual void setLoadPriority(
const QPointer<QObject>& owner,
float priority);
430 virtual void setLoadPriorities(
const QHash<QPointer<QObject>,
float>& priorities);
442 virtual bool isFailed()
const {
return _failedToLoad; }
454 float getProgress()
const {
return (_bytesTotal <= 0) ? 0.0f : (float)_bytesReceived / _bytesTotal; }
459 void setSelf(
const QWeakPointer<Resource>&
self) { _self =
self; }
463 virtual void deleter() { allReferencesCleared(); }
465 const QUrl& getURL()
const {
return _url; }
467 unsigned int getDownloadAttempts() {
return _attempts; }
468 unsigned int getDownloadAttemptsRemaining() {
return _attemptsRemaining; }
470 virtual void setExtra(
void* extra) {};
471 void setExtraHash(
size_t extraHash) { _extraHash = extraHash; }
472 size_t getExtraHash()
const {
return _extraHash; }
486 void failed(QNetworkReply::NetworkError error);
492 void onProgress(uint64_t bytesReceived, uint64_t bytesTotal);
498 void attemptRequest();
501 virtual void init(
bool resetLoaded =
true);
516 void setSize(
const qint64& bytes);
522 Q_INVOKABLE
void allReferencesCleared();
528 QUrl _effectiveBaseURL { _url };
530 ByteRange _requestByteRange;
531 bool _shouldFailOnRedirect {
false };
536 bool _startedLoading =
false;
537 bool _failedToLoad =
false;
538 bool _loaded =
false;
540 QHash<QPointer<QObject>,
float> _loadPriorities;
541 QWeakPointer<Resource> _self;
542 QPointer<ResourceCache> _cache;
544 qint64 _bytesReceived { 0 };
545 qint64 _bytesTotal { 0 };
549 ResourceRequest* _request {
nullptr };
551 size_t _extraHash { std::numeric_limits<size_t>::max() };
554 void handleDownloadProgress(uint64_t bytesReceived, uint64_t bytesTotal);
555 void handleReplyFinished();
561 void setLRUKey(
int lruKey) { _lruKey = lruKey; }
566 bool isInScript()
const {
return _isInScript; }
567 void setInScript(
bool isInScript) { _isInScript = isInScript; }
570 QTimer* _replyTimer{
nullptr };
571 unsigned int _attempts{ 0 };
572 static const int MAX_ATTEMPTS = 8;
573 unsigned int _attemptsRemaining { MAX_ATTEMPTS };
574 bool _isInScript{
false };
577 uint qHash(
const QPointer<QObject>& value, uint seed = 0);
Base class for resource caches.
Definition: ResourceCache.h:196
virtual QSharedPointer< Resource > createResource(const QUrl &url)=0
Creates a new resource.
static bool attemptRequest(QSharedPointer< Resource > resource)
Definition: ResourceCache.cpp:534
QSharedPointer< Resource > getResource(const QUrl &url, const QUrl &fallback=QUrl())
Definition: ResourceCache.h:248
Base class for resources.
Definition: ResourceCache.h:409
void loading()
Fired when the resource begins downloading.
qint64 getBytesReceived() const
For loading resources, returns the number of bytes received.
Definition: ResourceCache.h:445
virtual bool isCacheable() const
Checks whether the resource is cacheable.
Definition: ResourceCache.h:509
qint64 getBytes() const
For loaded resources, returns the number of actual bytes (defaults to total bytes if not explicitly s...
Definition: ResourceCache.h:451
virtual void refresh()
Refreshes the resource.
Definition: ResourceCache.cpp:647
virtual bool isLoaded() const
Checks whether the resource has loaded.
Definition: ResourceCache.h:439
virtual bool isFailed() const
Checks whether the resource has failed to download.
Definition: ResourceCache.h:442
void finished(bool success)
Fired when the resource has finished loading.
void onProgress(uint64_t bytesReceived, uint64_t bytesTotal)
Fired on progress updates.
void onRefresh()
Fired when the resource is refreshed.
float getProgress() const
For loading resources, returns the load progress.
Definition: ResourceCache.h:454
void loaded(const QByteArray request)
void failed(QNetworkReply::NetworkError error)
Fired when the resource failed to load.
float getLoadPriority()
Returns the highest load priority across all owners.
Definition: ResourceCache.cpp:630
virtual void setLoadPriority(const QPointer< QObject > &owner, float priority)
Sets the load priority for one owner.
Definition: ResourceCache.cpp:608
virtual void setLoadPriorities(const QHash< QPointer< QObject >, float > &priorities)
Sets a set of priorities at once.
Definition: ResourceCache.cpp:614
Q_INVOKABLE void finishedLoading(bool success)
Definition: ResourceCache.cpp:743
virtual void clearLoadPriority(const QPointer< QObject > &owner)
Clears the load priority for one owner.
Definition: ResourceCache.cpp:624
virtual void downloadFinished(const QByteArray &data)
Definition: ResourceCache.h:513
void setSize(const qint64 &bytes)
Called when the download is finished and processed, sets the number of actual bytes.
Definition: ResourceCache.cpp:753
int getLRUKey() const
Returns the key last used to identify this resource in the unused map.
Definition: ResourceCache.h:421
qint64 getBytesTotal() const
For loading resources, returns the number of total bytes (<= zero if unknown).
Definition: ResourceCache.h:448
virtual bool handleFailedRequest(ResourceRequest::Result result)
Return true if the resource will be retried.
Definition: ResourceCache.cpp:853
void ensureLoading()
Makes sure that the resource has started loading.
Definition: ResourceCache.cpp:602
virtual void makeRequest()
Definition: ResourceCache.cpp:764
void updateSize(qint64 deltaSize)
Fired when the size changes (through setSize).
Wrapper to expose resource caches to JS/QML.
Definition: ResourceCache.h:304
Wrapper to expose resources to JS/QML.
Definition: ResourceCache.h:91