From 1b7fdf5d16b76581ee5e29f688c8b4a8e57a5e6d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Mar 2015 18:49:52 +0100 Subject: [PATCH 1/6] Improve disk cache usage Now we always load from the disk cache if the file is in there. Then we check the last modidied date from the network file against the one in the cache. If needed, we redownload. --- libraries/networking/src/ResourceCache.cpp | 43 +++++++++++++++++++++- libraries/networking/src/ResourceCache.h | 6 ++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index 7eadb0a3dd..658f32aba1 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -12,9 +12,10 @@ #include #include +#include +#include #include #include -#include #include @@ -314,13 +315,51 @@ void Resource::handleReplyTimeout() { "received" << _bytesReceived << "total" << _bytesTotal); } +void Resource::maybeRefresh() { + if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) { + QNetworkReply* reply = qobject_cast(sender()); + QVariant variant = reply->header(QNetworkRequest::LastModifiedHeader); + QNetworkCacheMetaData metaData = NetworkAccessManager::getInstance().cache()->metaData(_url); + if (variant.isValid() && variant.canConvert() && metaData.isValid()) { + QDateTime lastModified = variant.value(); + QDateTime lastModifiedOld = metaData.lastModified(); + if (lastModified.isValid() && lastModifiedOld.isValid() && + lastModifiedOld == lastModified) { + // We don't need to update, return + return; + } + } + qDebug() << "Loaded" << _url.fileName() << "from the disk cache but the network version is newer, refreshing."; + refresh(); + } +} + 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); + 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)); + NetworkAccessManager::getInstance().cache()->updateMetaData(metaData); + } + } + } + _replyTimer = new QTimer(this); connect(_replyTimer, SIGNAL(timeout()), SLOT(handleReplyTimeout())); _replyTimer->setSingleShot(true); diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index 62fca71ea5..11b091a9e3 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -149,7 +149,7 @@ public: /// For loading resources, returns the load progress. float getProgress() const { return (_bytesTotal <= 0) ? 0.0f : (float)_bytesReceived / _bytesTotal; } - + /// Refreshes the resource. void refresh(); @@ -169,6 +169,10 @@ signals: protected slots: void attemptRequest(); + + /// Refreshes the resource if the last modified date on the network + /// is greater than the last modified date in the cache. + void maybeRefresh(); protected: From 9d7144dab04921ab7428f4e52ec083485f42dec8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Mar 2015 18:52:48 +0100 Subject: [PATCH 2/6] Bumped disk cache size to 10GB --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6484e364bc..96874f8593 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -141,7 +141,7 @@ using namespace std; static unsigned STARFIELD_NUM_STARS = 50000; static unsigned STARFIELD_SEED = 1; -const qint64 MAXIMUM_CACHE_SIZE = 10737418240; // 10GB +const qint64 MAXIMUM_CACHE_SIZE = 10 * BYTES_PER_GIGABYTES; // 10GB static QTimer* locationUpdateTimer = NULL; static QTimer* balanceUpdateTimer = NULL; From 53f23d8452ed15cd1107d99f6c6632cd361e3e85 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Mar 2015 21:08:14 +0100 Subject: [PATCH 3/6] Added disk cache editor --- interface/src/ui/DiskCacheEditor.cpp | 148 +++++++++++++++++++++++++++ interface/src/ui/DiskCacheEditor.h | 46 +++++++++ 2 files changed, 194 insertions(+) create mode 100644 interface/src/ui/DiskCacheEditor.cpp create mode 100644 interface/src/ui/DiskCacheEditor.h diff --git a/interface/src/ui/DiskCacheEditor.cpp b/interface/src/ui/DiskCacheEditor.cpp new file mode 100644 index 0000000000..d1987462e3 --- /dev/null +++ b/interface/src/ui/DiskCacheEditor.cpp @@ -0,0 +1,148 @@ +// +// DiskCacheEditor.cpp +// +// +// Created by Clement on 3/4/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "DiskCacheEditor.h" + +DiskCacheEditor::DiskCacheEditor(QWidget* parent) : QObject(parent) { + +} + +QWindow* DiskCacheEditor::windowHandle() { + return (_dialog) ? _dialog->windowHandle() : nullptr; +} + +void DiskCacheEditor::toggle() { + qDebug() << "DiskCacheEditor::toggle()"; + if (!_dialog) { + makeDialog(); + } + + if (!_dialog->isActiveWindow()) { + _dialog->show(); + _dialog->raise(); + _dialog->activateWindow(); + } else { + _dialog->close(); + } +} + +void DiskCacheEditor::makeDialog() { + _dialog = new QDialog(static_cast(parent())); + Q_CHECK_PTR(_dialog); + _dialog->setAttribute(Qt::WA_DeleteOnClose); + _dialog->setWindowTitle("Disk Cache Editor"); + + QGridLayout* layout = new QGridLayout(_dialog); + Q_CHECK_PTR(layout); + _dialog->setLayout(layout); + + + QLabel* path = new QLabel("Path : ", _dialog); + Q_CHECK_PTR(path); + path->setAlignment(Qt::AlignRight); + layout->addWidget(path, 0, 0); + + QLabel* size = new QLabel("Max Size : ", _dialog); + Q_CHECK_PTR(size); + size->setAlignment(Qt::AlignRight); + layout->addWidget(size, 1, 0); + + QLabel* maxSize = new QLabel("Current Size : ", _dialog); + Q_CHECK_PTR(maxSize); + maxSize->setAlignment(Qt::AlignRight); + layout->addWidget(maxSize, 2, 0); + + + _path = new QLabel(_dialog); + Q_CHECK_PTR(_path); + _path->setAlignment(Qt::AlignLeft); + layout->addWidget(_path, 0, 1, 1, 3); + + _size = new QLabel(_dialog); + Q_CHECK_PTR(_size); + _size->setAlignment(Qt::AlignLeft); + layout->addWidget(_size, 1, 1, 1, 3); + + _maxSize = new QLabel(_dialog); + Q_CHECK_PTR(_maxSize); + _maxSize->setAlignment(Qt::AlignLeft); + layout->addWidget(_maxSize, 2, 1, 1, 3); + + refresh(); + + + QPushButton* refreshCacheButton = new QPushButton(_dialog); + Q_CHECK_PTR(refreshCacheButton); + refreshCacheButton->setText("Refresh"); + refreshCacheButton->setToolTip("Reload the cache stats."); + connect(refreshCacheButton, SIGNAL(clicked()), SLOT(refresh())); + layout->addWidget(refreshCacheButton, 3, 2); + + QPushButton* clearCacheButton = new QPushButton(_dialog); + Q_CHECK_PTR(clearCacheButton); + clearCacheButton->setText("Clear"); + clearCacheButton->setToolTip("Erases the entire content of the disk cache."); + connect(clearCacheButton, SIGNAL(clicked()), SLOT(clear())); + layout->addWidget(clearCacheButton, 3, 3); +} + +void DiskCacheEditor::refresh() { + static const std::function stringify = [](qint64 number) { + static const QStringList UNITS = QStringList() << "B" << "KB" << "MB" << "GB"; + static const qint64 CHUNK = 1024; + QString unit; + int i = 0; + for (i = 0; i < 4; ++i) { + if (number / CHUNK > 0) { + number /= CHUNK; + } else { + break; + } + } + return QString("%0 %1").arg(number).arg(UNITS[i]); + }; + QNetworkDiskCache* cache = qobject_cast(NetworkAccessManager::getInstance().cache()); + + if (_path) { + _path->setText(cache->cacheDirectory()); + } + if (_size) { + _size->setText(stringify(cache->cacheSize())); + } + if (_maxSize) { + _maxSize->setText(stringify(cache->maximumCacheSize())); + } +} + +void DiskCacheEditor::clear() { + QMessageBox::StandardButton buttonClicked = + QMessageBox::question(_dialog, "Clearing disk cache", + "You are about to erase all the content of the disk cache," + "are you sure you want to do that?"); + if (buttonClicked == QMessageBox::Yes) { + QNetworkDiskCache* cache = qobject_cast(NetworkAccessManager::getInstance().cache()); + if (cache) { + qDebug() << "DiskCacheEditor::clear(): Clearing disk cache."; + cache->clear(); + } + } + refresh(); +} diff --git a/interface/src/ui/DiskCacheEditor.h b/interface/src/ui/DiskCacheEditor.h new file mode 100644 index 0000000000..5d673c4285 --- /dev/null +++ b/interface/src/ui/DiskCacheEditor.h @@ -0,0 +1,46 @@ +// +// DiskCacheEditor.h +// +// +// Created by Clement on 3/4/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_DiskCacheEditor_h +#define hifi_DiskCacheEditor_h + +#include +#include + +class QDialog; +class QLabel; +class QWindow; + +class DiskCacheEditor : public QObject { + Q_OBJECT + +public: + DiskCacheEditor(QWidget* parent = nullptr); + + QWindow* windowHandle(); + +public slots: + void toggle(); + +private slots: + void refresh(); + void clear(); + +private: + void makeDialog(); + + QPointer _dialog; + QPointer _path; + QPointer _size; + QPointer _maxSize; +}; + +#endif // hifi_DiskCacheEditor_h \ No newline at end of file From 908e946ac5c606929137c17090975898d5faa967 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Mar 2015 21:09:23 +0100 Subject: [PATCH 4/6] Hook up disk cache to the dialog manager --- interface/src/ui/DialogsManager.cpp | 7 ++++++- interface/src/ui/DialogsManager.h | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 2452369c18..ad963e8af3 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -20,6 +20,7 @@ #include "AttachmentsDialog.h" #include "BandwidthDialog.h" #include "CachesSizeDialog.h" +#include "DiskCacheEditor.h" #include "HMDToolsDialog.h" #include "LodToolsDialog.h" #include "LoginDialog.h" @@ -37,6 +38,11 @@ void DialogsManager::toggleAddressBar() { } } +void DialogsManager::toggleDiskCacheEditor() { + maybeCreateDialog(_diskCacheEditor); + _diskCacheEditor->toggle(); +} + void DialogsManager::toggleLoginDialog() { maybeCreateDialog(_loginDialog); _loginDialog->toggleQAction(); @@ -61,7 +67,6 @@ void DialogsManager::octreeStatsDetails() { } void DialogsManager::cachesSizeDialog() { - qDebug() << "Caches size:" << _cachesSizeDialog.isNull(); if (!_cachesSizeDialog) { maybeCreateDialog(_cachesSizeDialog); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index e2da71bbd8..897215cbff 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -24,8 +24,9 @@ class QAction; class AddressBarDialog; class AnimationsDialog; class AttachmentsDialog; -class CachesSizeDialog; class BandwidthDialog; +class CachesSizeDialog; +class DiskCacheEditor; class LodToolsDialog; class LoginDialog; class OctreeStatsDialog; @@ -45,6 +46,7 @@ public: public slots: void toggleAddressBar(); + void toggleDiskCacheEditor(); void toggleLoginDialog(); void showLoginDialog(); void octreeStatsDetails(); @@ -73,7 +75,7 @@ private: member = new T(parent); Q_CHECK_PTR(member); - if (_hmdToolsDialog) { + if (_hmdToolsDialog && member->windowHandle()) { _hmdToolsDialog->watchWindow(member->windowHandle()); } } @@ -84,6 +86,7 @@ private: QPointer _attachmentsDialog; QPointer _bandwidthDialog; QPointer _cachesSizeDialog; + QPointer _diskCacheEditor; QPointer _ircInfoBox; QPointer _hmdToolsDialog; QPointer _lodToolsDialog; From f4d8ee39dcae0587138dc48681af3063834c47df Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Mar 2015 21:10:02 +0100 Subject: [PATCH 5/6] Menu item for cache editor --- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 2 ++ interface/src/Menu.h | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 96874f8593..3454557fe9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -445,7 +445,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : cache->setMaximumCacheSize(MAXIMUM_CACHE_SIZE); cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache"); networkAccessManager.setCache(cache); - + ResourceCache::setRequestLimit(3); _window->setCentralWidget(_glWidget); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 59d6734b2a..ea63b9879f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -436,6 +436,8 @@ Menu::Menu() { SLOT(disable(bool))); addActionToQMenuAndActionHash(networkMenu, MenuOption::CachesSize, 0, dialogsManager.data(), SLOT(cachesSizeDialog())); + addActionToQMenuAndActionHash(networkMenu, MenuOption::DiskCacheEditor, 0, + dialogsManager.data(), SLOT(toggleDiskCacheEditor())); QMenu* timingMenu = developerMenu->addMenu("Timing and Stats"); QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index fe1035d54b..3166e1fa37 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -125,7 +125,7 @@ namespace MenuOption { const QString BookmarkLocation = "Bookmark Location"; const QString Bookmarks = "Bookmarks"; const QString CascadedShadows = "Cascaded"; - const QString CachesSize = "Caches Size"; + const QString CachesSize = "RAM Caches Size"; const QString Chat = "Chat..."; const QString ChatCircling = "Chat Circling"; const QString CollideAsRagdoll = "Collide With Self (Ragdoll)"; @@ -143,6 +143,7 @@ namespace MenuOption { const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD"; const QString DisableLightEntities = "Disable Light Entities"; const QString DisableNackPackets = "Disable NACK Packets"; + const QString DiskCacheEditor = "Disk Cache Editor"; const QString DisplayHands = "Show Hand Info"; const QString DisplayHandTargets = "Show Hand Targets"; const QString DisplayModelBounds = "Display Model Bounds"; From 7690301e582ec54d9947fefc86f6294313cdfba6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 5 Mar 2015 21:49:22 +0100 Subject: [PATCH 6/6] Include functional --- interface/src/ui/DiskCacheEditor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/ui/DiskCacheEditor.cpp b/interface/src/ui/DiskCacheEditor.cpp index d1987462e3..38fd1cb383 100644 --- a/interface/src/ui/DiskCacheEditor.cpp +++ b/interface/src/ui/DiskCacheEditor.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include #include