Merge pull request #4381 from Atlante45/disk_cache

Disk cache tweaks
This commit is contained in:
Brad Hefta-Gaub 2015-03-08 11:40:40 -07:00
commit 21cd7e36e0
9 changed files with 259 additions and 9 deletions

View file

@ -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;
@ -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);

View file

@ -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");

View file

@ -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";

View file

@ -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);

View file

@ -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> _attachmentsDialog;
QPointer<BandwidthDialog> _bandwidthDialog;
QPointer<CachesSizeDialog> _cachesSizeDialog;
QPointer<DiskCacheEditor> _diskCacheEditor;
QPointer<QMessageBox> _ircInfoBox;
QPointer<HMDToolsDialog> _hmdToolsDialog;
QPointer<LodToolsDialog> _lodToolsDialog;

View file

@ -0,0 +1,150 @@
//
// 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 <functional>
#include <QDebug>
#include <QDialog>
#include <QGridLayout>
#include <QPushButton>
#include <QLabel>
#include <QNetworkDiskCache>
#include <QMessageBox>
#include <NetworkAccessManager.h>
#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<QWidget*>(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<QString(qint64)> 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<QNetworkDiskCache*>(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<QNetworkDiskCache*>(NetworkAccessManager::getInstance().cache());
if (cache) {
qDebug() << "DiskCacheEditor::clear(): Clearing disk cache.";
cache->clear();
}
}
refresh();
}

View file

@ -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 <QObject>
#include <QPointer>
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<QDialog> _dialog;
QPointer<QLabel> _path;
QPointer<QLabel> _size;
QPointer<QLabel> _maxSize;
};
#endif // hifi_DiskCacheEditor_h

View file

@ -12,9 +12,10 @@
#include <cfloat>
#include <cmath>
#include <QDebug>
#include <QNetworkDiskCache>
#include <QThread>
#include <QTimer>
#include <QtDebug>
#include <SharedUtil.h>
@ -314,13 +315,51 @@ void Resource::handleReplyTimeout() {
"received" << _bytesReceived << "total" << _bytesTotal);
}
void Resource::maybeRefresh() {
if (Q_LIKELY(NetworkAccessManager::getInstance().cache())) {
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
QVariant variant = reply->header(QNetworkRequest::LastModifiedHeader);
QNetworkCacheMetaData metaData = NetworkAccessManager::getInstance().cache()->metaData(_url);
if (variant.isValid() && variant.canConvert<QDateTime>() && metaData.isValid()) {
QDateTime lastModified = variant.value<QDateTime>();
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);

View file

@ -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: