14 #ifndef hifi_ResourceCache_h
15 #define hifi_ResourceCache_h
21 #include <QtCore/QHash>
22 #include <QtCore/QList>
23 #include <QtCore/QObject>
24 #include <QtCore/QPointer>
25 #include <QtCore/QSharedPointer>
26 #include <QtCore/QUrl>
27 #include <QtCore/QWeakPointer>
28 #include <QtCore/QReadWriteLock>
29 #include <QtCore/QQueue>
31 #include <QtNetwork/QNetworkReply>
32 #include <QtNetwork/QNetworkRequest>
34 #include <DependencyManager.h>
36 #include "ResourceManager.h"
38 Q_DECLARE_METATYPE(
size_t)
45 static const qint64 BYTES_PER_MEGABYTES = 1024 * 1024;
46 static const qint64 BYTES_PER_GIGABYTES = 1024 * BYTES_PER_MEGABYTES;
47 static const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES;
52 static const qint64 DEFAULT_UNUSED_MAX_SIZE = 100 * BYTES_PER_MEGABYTES;
54 static const qint64 DEFAULT_UNUSED_MAX_SIZE = 1024 * BYTES_PER_MEGABYTES;
56 static const qint64 MIN_UNUSED_MAX_SIZE = 0;
57 static const qint64 MAX_UNUSED_MAX_SIZE = MAXIMUM_CACHE_SIZE;
63 class ResourceCacheSharedItems :
public Dependency {
66 using Mutex = std::recursive_mutex;
67 using Lock = std::unique_lock<Mutex>;
70 bool appendRequest(QWeakPointer<Resource> newRequest,
float priority);
71 void removeRequest(QWeakPointer<Resource> doneRequest);
72 void setRequestLimit(uint32_t limit);
73 uint32_t getRequestLimit()
const;
74 QList<QSharedPointer<Resource>> getPendingRequests()
const;
75 std::pair<QSharedPointer<Resource>,
float> getHighestPendingRequest();
76 uint32_t getPendingRequestsCount()
const;
77 QList<std::pair<QSharedPointer<Resource>,
float>> getLoadingRequests()
const;
78 uint32_t getLoadingRequestsCount()
const;
82 ResourceCacheSharedItems() =
default;
85 QList<QWeakPointer<Resource>> _pendingRequests;
86 QList<std::pair<QWeakPointer<Resource>,
float>> _loadingRequests;
87 const uint32_t DEFAULT_REQUEST_LIMIT = 10;
88 uint32_t _requestLimit { DEFAULT_REQUEST_LIMIT };
111 Q_PROPERTY(QUrl url READ getURL)
112 Q_PROPERTY(
int state READ getState NOTIFY stateChanged)
141 Q_INVOKABLE
void release();
143 const QUrl& getURL()
const {
return _url; }
144 int getState()
const {
return (
int)_state; }
145 const QSharedPointer<Resource>& getResource()
const {
return _resource; }
147 bool isInScript()
const;
148 void setInScript(
bool isInScript);
159 void progressChanged(uint64_t bytesReceived, uint64_t bytesTotal);
167 void stateChanged(
int state);
170 void setState(State state) { _state = state; emit stateChanged(_state); }
173 void loadingChanged();
174 void loadedChanged();
175 void finished(
bool success);
178 void disconnectHelper();
183 QSharedPointer<Resource> _resource;
185 QMetaObject::Connection _progressConnection;
186 QMetaObject::Connection _loadingConnection;
187 QMetaObject::Connection _loadedConnection;
188 QMetaObject::Connection _finishedConnection;
191 State _state{ QUEUED };
200 Q_PROPERTY(
size_t numTotal READ getNumTotalResources NOTIFY dirty)
201 Q_PROPERTY(
size_t numCached READ getNumCachedResources NOTIFY dirty)
202 Q_PROPERTY(
size_t sizeTotal READ getSizeTotalResources NOTIFY dirty)
203 Q_PROPERTY(
size_t sizeCached READ getSizeCachedResources NOTIFY dirty)
207 size_t getNumTotalResources()
const {
return _numTotalResources; }
208 size_t getSizeTotalResources()
const {
return _totalResourcesSize; }
209 size_t getNumCachedResources()
const {
return _numUnusedResources; }
210 size_t getSizeCachedResources()
const {
return _unusedResourcesSize; }
212 Q_INVOKABLE QVariantList getResourceList();
214 static void setRequestLimit(uint32_t limit);
215 static uint32_t getRequestLimit() {
return DependencyManager::get<ResourceCacheSharedItems>()->getRequestLimit(); }
217 void setUnusedResourceCacheSize(qint64 unusedResourcesMaxSize);
218 qint64 getUnusedResourceCacheSize()
const {
return _unusedResourcesMaxSize; }
220 static QList<std::pair<QSharedPointer<Resource>,
float>> getLoadingRequests();
221 static uint32_t getPendingRequestCount();
222 static uint32_t getLoadingRequestCount();
228 void clearUnusedResources();
236 void updateTotalSize(
const qint64& deltaSize);
249 QSharedPointer<Resource>
getResource(
const QUrl& url,
const QUrl& fallback = QUrl()) {
return getResource(url, fallback,
nullptr, std::numeric_limits<size_t>::max()); }
250 QSharedPointer<Resource>
getResource(
const QUrl& url,
const QUrl& fallback,
void* extra,
size_t extraHash);
253 void clearATPAssets();
261 Q_INVOKABLE
ScriptableResource* prefetch(
const QUrl& url) {
return prefetch(url,
nullptr, std::numeric_limits<size_t>::max()); }
266 ScriptableResource* prefetchAndMoveToThread(
const QUrl& url,
void* extra,
size_t extraHash, QThread *scriptThread);
270 virtual QSharedPointer<Resource> createResourceCopy(
const QSharedPointer<Resource>& resource) = 0;
272 void addUnusedResource(
const QSharedPointer<Resource>& resource);
273 void removeUnusedResource(
const QSharedPointer<Resource>& resource);
277 static bool attemptRequest(QSharedPointer<Resource> resource,
float priority = NAN);
278 static void requestCompleted(QWeakPointer<Resource> resource);
279 static bool attemptHighestPriorityRequest();
285 void reserveUnusedResource(qint64 resourceSize);
286 void removeResource(
const QUrl& url,
size_t extraHash, qint64 size = 0);
288 void resetTotalResourceCounter();
289 void resetUnusedResourceCounter();
290 void resetResourceCounters();
293 QHash<QUrl, QMultiHash<size_t, QWeakPointer<Resource>>> _resources;
294 QReadWriteLock _resourcesLock { QReadWriteLock::Recursive };
297 std::atomic<size_t> _numTotalResources { 0 };
298 std::atomic<qint64> _totalResourcesSize { 0 };
301 QMap<int, QSharedPointer<Resource>> _unusedResources;
302 QReadWriteLock _unusedResourcesLock { QReadWriteLock::Recursive };
303 qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE;
305 std::atomic<size_t> _numUnusedResources { 0 };
306 std::atomic<qint64> _unusedResourcesSize { 0 };
322 Q_PROPERTY(
size_t numTotal READ getNumTotalResources NOTIFY dirty)
323 Q_PROPERTY(
size_t numCached READ getNumCachedResources NOTIFY dirty)
324 Q_PROPERTY(
size_t sizeTotal READ getSizeTotalResources NOTIFY dirty)
325 Q_PROPERTY(
size_t sizeCached READ getSizeCachedResources NOTIFY dirty)
333 Q_PROPERTY(
size_t numGlobalQueriesPending READ getNumGlobalQueriesPending NOTIFY dirty)
334 Q_PROPERTY(
size_t numGlobalQueriesLoading READ getNumGlobalQueriesLoading NOTIFY dirty)
349 Q_INVOKABLE QVariantList getResourceList();
356 Q_INVOKABLE
void updateTotalSize(
const qint64& deltaSize);
388 Q_INVOKABLE
ScriptableResource* prefetch(
const QUrl& url) {
return prefetch(url,
nullptr, std::numeric_limits<size_t>::max()); }
391 Q_INVOKABLE
ScriptableResource* prefetch(
const QUrl& url,
void* extra,
size_t extraHash);
403 QSharedPointer<ResourceCache> _resourceCache;
405 size_t getNumTotalResources()
const {
return _resourceCache->getNumTotalResources(); }
406 size_t getSizeTotalResources()
const {
return _resourceCache->getSizeTotalResources(); }
407 size_t getNumCachedResources()
const {
return _resourceCache->getNumCachedResources(); }
408 size_t getSizeCachedResources()
const {
return _resourceCache->getSizeCachedResources(); }
410 size_t getNumGlobalQueriesPending()
const {
return ResourceCache::getPendingRequestCount(); }
411 size_t getNumGlobalQueriesLoading()
const {
return ResourceCache::getLoadingRequestCount(); }
419 Resource() : QObject(), _loaded(
true) {}
424 virtual QString getType()
const {
return "Resource"; }
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>, std::function<float()>> _loadPriorityOperators;
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:197
static bool attemptRequest(QSharedPointer< Resource > resource, float priority=NAN)
Definition: ResourceCache.cpp:540
virtual QSharedPointer< Resource > createResource(const QUrl &url)=0
Creates a new resource.
QSharedPointer< Resource > getResource(const QUrl &url, const QUrl &fallback=QUrl())
Definition: ResourceCache.h:249
Base class for resources.
Definition: ResourceCache.h:415
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:637
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.
virtual void setLoadPriorityOperator(const QPointer< QObject > &owner, std::function< float()> priorityOperator)
Sets the load priority for one owner.
Definition: ResourceCache.cpp:614
float getLoadPriority()
Returns the highest load priority across all owners.
Definition: ResourceCache.cpp:620
Q_INVOKABLE void finishedLoading(bool success)
Definition: ResourceCache.cpp:733
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:743
int getLRUKey() const
Returns the key last used to identify this resource in the unused map.
Definition: ResourceCache.h:427
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:843
void ensureLoading()
Makes sure that the resource has started loading.
Definition: ResourceCache.cpp:608
virtual void makeRequest()
Definition: ResourceCache.cpp:754
void updateSize(qint64 deltaSize)
Fired when the size changes (through setSize).
Wrapper to expose resource caches to JS/QML.
Definition: ResourceCache.h:310
Wrapper to expose resources to JS/QML.
Definition: ResourceCache.h:92