Implement download caching. Set the folder for the cache data in the configuration dialog. Caching is disabled per default and defaults to the systems temp folder.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14476 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dominik Riebeling 2007-08-27 17:40:35 +00:00
parent 0877a1a9f5
commit 5ef236869f
12 changed files with 206 additions and 19 deletions

View file

@ -66,14 +66,9 @@ Config::Config(QWidget *parent) : QDialog(parent)
connect(ui.radioSystemProxy, SIGNAL(toggled(bool)), this, SLOT(setSystemProxy(bool))); connect(ui.radioSystemProxy, SIGNAL(toggled(bool)), this, SLOT(setSystemProxy(bool)));
connect(ui.browseMountPoint, SIGNAL(clicked()), this, SLOT(browseFolder())); connect(ui.browseMountPoint, SIGNAL(clicked()), this, SLOT(browseFolder()));
connect(ui.buttonAutodetect,SIGNAL(clicked()),this,SLOT(autodetect())); connect(ui.buttonAutodetect,SIGNAL(clicked()),this,SLOT(autodetect()));
connect(ui.buttonCacheBrowse, SIGNAL(clicked()), this, SLOT(browseCache()));
// disable unimplemented stuff connect(ui.buttonCacheClear, SIGNAL(clicked()), this, SLOT(cacheClear()));
ui.buttonCacheBrowse->setEnabled(false);
ui.cacheDisable->setEnabled(false);
ui.cacheOfflineMode->setEnabled(false);
ui.buttonCacheClear->setEnabled(false);
//ui.buttonAutodetect->setEnabled(false);
} }
@ -116,6 +111,14 @@ void Config::accept()
userSettings->setValue("defaults/platform", nplat); userSettings->setValue("defaults/platform", nplat);
} }
// cache settings
if(QFileInfo(ui.cachePath->text()).isDir())
userSettings->setValue("defaults/cachepath", ui.cachePath->text());
else // default to system temp path
userSettings->setValue("defaults/cachepath", QDir::tempPath());
userSettings->setValue("defaults/cachedisable", ui.cacheDisable->isChecked());
userSettings->setValue("defaults/offline", ui.cacheOfflineMode->isChecked());
// sync settings // sync settings
userSettings->sync(); userSettings->sync();
this->close(); this->close();
@ -169,6 +172,20 @@ void Config::setUserSettings(QSettings *user)
// devices tab // devices tab
ui.mountPoint->setText(userSettings->value("defaults/mountpoint").toString()); ui.mountPoint->setText(userSettings->value("defaults/mountpoint").toString());
// cache tab
if(!QFileInfo(userSettings->value("defaults/cachepath").toString()).isDir())
userSettings->setValue("defaults/cachepath", QDir::tempPath());
ui.cachePath->setText(userSettings->value("defaults/cachepath").toString());
ui.cacheDisable->setChecked(userSettings->value("defaults/cachedisable").toBool());
ui.cacheOfflineMode->setChecked(userSettings->value("defaults/offline").toBool());
QList<QFileInfo> fs = QDir(userSettings->value("defaults/cachepath").toString() + "/rbutil-cache/").entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
qint64 sz = 0;
for(int i = 0; i < fs.size(); i++) {
sz += fs.at(i).size();
qDebug() << fs.at(i).fileName() << fs.at(i).size();
}
ui.cacheSize->setText(tr("Current cache size is %1 kiB.")
.arg(sz/1024));
} }
@ -344,12 +361,32 @@ void Config::browseFolder()
} }
void Config::browseCache()
{
cbrowser = new BrowseDirtree(this);
#if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
cbrowser->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
#elif defined(Q_OS_WIN32)
cbrowser->setFilter(QDir::Drives);
#endif
QDir d(ui.cachePath->text());
cbrowser->setDir(d);
cbrowser->show();
connect(cbrowser, SIGNAL(itemChanged(QString)), this, SLOT(setCache(QString)));
}
void Config::setMountpoint(QString m) void Config::setMountpoint(QString m)
{ {
ui.mountPoint->setText(m); ui.mountPoint->setText(m);
} }
void Config::setCache(QString c)
{
ui.cachePath->setText(c);
}
void Config::autodetect() void Config::autodetect()
{ {
Autodetection detector(this); Autodetection detector(this);
@ -403,3 +440,29 @@ void Config::autodetect()
} }
} }
void Config::cacheClear()
{
if(QMessageBox::critical(this, tr("Really delete cache?"),
tr("Do you really want to delete the cache? "
"Make absolutely sure this setting is correct as it will "
"remove <b>all</b> files in this folder!").arg(ui.cachePath->text()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
return;
QString cache = ui.cachePath->text() + "/rbutil-cache/";
if(!QFileInfo(cache).isDir()) {
QMessageBox::critical(this, tr("Path wrong!"),
tr("The cache path is invalid. Aborting."), QMessageBox::Ok);
return;
}
QDir dir(cache);
QStringList fn;
fn = dir.entryList(QStringList("*"), QDir::Files, QDir::Name);
qDebug() << fn;
for(int i = 0; i < fn.size(); i++) {
QString f = cache + fn.at(i);
QFile::remove(f);
qDebug() << "removed:" << f;
}
}

View file

@ -51,14 +51,18 @@ class Config : public QDialog
QUrl proxy; QUrl proxy;
BrowseDirtree *browser; BrowseDirtree *browser;
BrowseDirtree *cbrowser;
private slots: private slots:
void setNoProxy(bool); void setNoProxy(bool);
void setSystemProxy(bool); void setSystemProxy(bool);
void updateLanguage(void); void updateLanguage(void);
void browseFolder(void); void browseFolder(void);
void browseCache(void);
void autodetect(void); void autodetect(void);
void setMountpoint(QString); void setMountpoint(QString);
void setCache(QString);
void cacheClear(void);
}; };
#endif #endif

View file

@ -270,6 +270,9 @@
<attribute name="title" > <attribute name="title" >
<string>Cac&amp;he</string> <string>Cac&amp;he</string>
</attribute> </attribute>
<attribute name="icon" >
<iconset resource="rbutilqt.qrc" >:/icons/icons/package-x-generic.png</iconset>
</attribute>
<attribute name="toolTip" > <attribute name="toolTip" >
<string>Download cache settings</string> <string>Download cache settings</string>
</attribute> </attribute>
@ -304,7 +307,11 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLineEdit" name="cachePath" /> <widget class="QLineEdit" name="cachePath" >
<property name="toolTip" >
<string>Entering an invalid folder will reset the path to the systems temporary path.</string>
</property>
</widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="buttonCacheBrowse" > <widget class="QPushButton" name="buttonCacheBrowse" >
@ -329,6 +336,9 @@
</item> </item>
<item> <item>
<widget class="QCheckBox" name="cacheOfflineMode" > <widget class="QCheckBox" name="cacheOfflineMode" >
<property name="toolTip" >
<string>This will try to use all information from the cache, even information about updates. Only use this option if you want to install without network connection. Note: you need to do the same install you want to perform later with network access first to download all required files to the cache.</string>
</property>
<property name="text" > <property name="text" >
<string>O&amp;ffline mode</string> <string>O&amp;ffline mode</string>
</property> </property>
@ -367,6 +377,9 @@
<property name="text" > <property name="text" >
<string>Clean cache &amp;now</string> <string>Clean cache &amp;now</string>
</property> </property>
<property name="icon" >
<iconset resource="rbutilqt.qrc" >:/icons/icons/user-trash-full.png</iconset>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>

View file

@ -27,8 +27,10 @@
HttpGet::HttpGet(QObject *parent) HttpGet::HttpGet(QObject *parent)
: QObject(parent) : QObject(parent)
{ {
m_usecache = false;
qDebug() << "--> HttpGet::HttpGet()"; qDebug() << "--> HttpGet::HttpGet()";
outputToBuffer = true; outputToBuffer = true;
cached = false;
getRequest = -1; getRequest = -1;
connect(&http, SIGNAL(done(bool)), this, SLOT(httpDone(bool))); connect(&http, SIGNAL(done(bool)), this, SLOT(httpDone(bool)));
connect(&http, SIGNAL(dataReadProgress(int, int)), this, SLOT(httpProgress(int, int))); connect(&http, SIGNAL(dataReadProgress(int, int)), this, SLOT(httpProgress(int, int)));
@ -42,6 +44,27 @@ HttpGet::HttpGet(QObject *parent)
} }
void HttpGet::setCache(QDir d)
{
m_cachedir = d;
bool result = true;
QString p = m_cachedir.absolutePath() + "/rbutil-cache";
if(QFileInfo(m_cachedir.absolutePath()).isDir())
if(!QFileInfo(p).isDir())
result = m_cachedir.mkdir("rbutil-cache");
else result = false;
qDebug() << "HttpGet::setCache(QDir)" << result;
m_usecache = !result;
}
void HttpGet::setCache(bool c)
{
m_usecache = c;
}
QByteArray HttpGet::readAll() QByteArray HttpGet::readAll()
{ {
return dataBuffer; return dataBuffer;
@ -108,6 +131,40 @@ bool HttpGet::getFile(const QUrl &url)
return false; return false;
} }
} }
// put hash generation here so it can get reused later
QString hash = QCryptographicHash::hash(url.toEncoded(), QCryptographicHash::Md5).toHex();
cachefile = m_cachedir.absolutePath() + "/rbutil-cache/" + hash;
if(m_usecache) {
// check if the file is present in cache
qDebug() << "[HTTP] cache ENABLED for" << url.toEncoded();
if(QFileInfo(cachefile).isReadable() && QFileInfo(cachefile).size() > 0) {
qDebug() << "[HTTP] cached file found!" << cachefile;
getRequest = -1;
QFile c(cachefile);
if(!outputToBuffer) {
qDebug() << outputFile->fileName();
c.open(QIODevice::ReadOnly);
outputFile->open(QIODevice::ReadWrite);
outputFile->write(c.readAll());
outputFile->close();
c.close();
}
else {
c.open(QIODevice::ReadOnly);
dataBuffer = c.readAll();
c.close();
}
response = 200; // fake "200 OK" HTTP response
cached = true;
httpDone(false); // we're done now. This will emit the correct signal too.
return true;
}
else qDebug() << "[HTTP] file not cached, downloading to" << cachefile;
}
else {
qDebug() << "[HTTP] cache DISABLED";
}
http.setHost(url.host(), url.port(80)); http.setHost(url.host(), url.port(80));
// construct query (if any) // construct query (if any)
QList<QPair<QString, QString> > qitems = url.queryItems(); QList<QPair<QString, QString> > qitems = url.queryItems();
@ -119,14 +176,14 @@ bool HttpGet::getFile(const QUrl &url)
} }
if(outputToBuffer) { if(outputToBuffer) {
qDebug() << "downloading to buffer:" << url.toString(); qDebug() << "[HTTP] downloading to buffer:" << url.toString();
getRequest = http.get(url.path() + query); getRequest = http.get(url.path() + query);
} }
else { else {
qDebug() << "downloading to file:" << url.toString() << qPrintable(outputFile->fileName()); qDebug() << "[HTTP] downloading to file:" << url.toString() << qPrintable(outputFile->fileName());
getRequest = http.get(url.path() + query, outputFile); getRequest = http.get(url.path() + query, outputFile);
} }
qDebug() << "request scheduled: GET" << getRequest; qDebug() << "[HTTP] request scheduled: GET" << getRequest;
return true; return true;
} }
@ -135,11 +192,25 @@ bool HttpGet::getFile(const QUrl &url)
void HttpGet::httpDone(bool error) void HttpGet::httpDone(bool error)
{ {
if (error) { if (error) {
qDebug() << "Error: " << qPrintable(http.errorString()) << httpResponse(); qDebug() << "[HTTP] Error: " << qPrintable(http.errorString()) << httpResponse();
} }
if(!outputToBuffer) if(!outputToBuffer)
outputFile->close(); outputFile->close();
if(m_usecache && !cached) {
qDebug() << "[HTTP] creating cache file" << cachefile;
QFile c(cachefile);
c.open(QIODevice::ReadWrite);
if(!outputToBuffer) {
outputFile->open(QIODevice::ReadOnly | QIODevice::Truncate);
c.write(outputFile->readAll());
outputFile->close();
}
else
c.write(dataBuffer);
c.close();
}
emit done(error); emit done(error);
} }

View file

@ -21,8 +21,8 @@
#ifndef HTTPGET_H #ifndef HTTPGET_H
#define HTTPGET_H #define HTTPGET_H
#include <QFile> #include <QtCore>
#include <QHttp> #include <QtNetwork>
class QUrl; class QUrl;
@ -38,8 +38,11 @@ class HttpGet : public QObject
QHttp::Error error(void); QHttp::Error error(void);
QString errorString(void); QString errorString(void);
void setFile(QFile*); void setFile(QFile*);
void setCache(QDir);
void setCache(bool);
int httpResponse(void); int httpResponse(void);
QByteArray readAll(void); QByteArray readAll(void);
bool isCached() { return cached; }
public slots: public slots:
void abort(void); void abort(void);
@ -65,6 +68,10 @@ class HttpGet : public QObject
QByteArray dataBuffer; QByteArray dataBuffer;
bool outputToBuffer; bool outputToBuffer;
QString query; QString query;
bool m_usecache;
QDir m_cachedir;
QString cachefile;
bool cached;
}; };
#endif #endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

View file

@ -99,6 +99,8 @@ void Install::accept()
installer->setUrl(file); installer->setUrl(file);
installer->setProxy(proxy); installer->setProxy(proxy);
installer->setLogSection("rockboxbase"); installer->setLogSection("rockboxbase");
if(!userSettings->value("defaults/cachedisable").toBool())
installer->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
installer->setLogVersion(myversion); installer->setLogVersion(myversion);
installer->setMountPoint(mountPoint); installer->setMountPoint(mountPoint);
installer->install(logger); installer->install(logger);

View file

@ -77,6 +77,8 @@ void ThemesInstallWindow::downloadInfo()
qDebug() << "downloadInfo()" << url; qDebug() << "downloadInfo()" << url;
qDebug() << url.queryItems(); qDebug() << url.queryItems();
getter->setProxy(proxy); getter->setProxy(proxy);
if(userSettings->value("defaults/offline").toBool())
getter->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
getter->setFile(&themesInfo); getter->setFile(&themesInfo);
getter->getFile(url); getter->getFile(url);
} }
@ -182,6 +184,8 @@ void ThemesInstallWindow::updateDetails(int row)
igetter.abort(); igetter.abort();
igetter.setProxy(proxy); igetter.setProxy(proxy);
if(!userSettings->value("defaults/cachedisable").toBool())
igetter.setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
igetter.getFile(img); igetter.getFile(img);
connect(&igetter, SIGNAL(done(bool)), this, SLOT(updateImage(bool))); connect(&igetter, SIGNAL(done(bool)), this, SLOT(updateImage(bool)));
} }
@ -294,6 +298,8 @@ void ThemesInstallWindow::accept()
installer->setLogSection(names); installer->setLogSection(names);
installer->setLogVersion(version); installer->setLogVersion(version);
installer->setMountPoint(mountPoint); installer->setMountPoint(mountPoint);
if(!userSettings->value("defaults/cachedisable").toBool())
installer->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
installer->install(logger); installer->install(logger);
connect(logger, SIGNAL(closed()), this, SLOT(close())); connect(logger, SIGNAL(closed()), this, SLOT(close()));
} }

View file

@ -25,6 +25,7 @@
ZipInstaller::ZipInstaller(QObject* parent): QObject(parent) ZipInstaller::ZipInstaller(QObject* parent): QObject(parent)
{ {
m_unzip = true; m_unzip = true;
m_cache = "";
} }
@ -86,6 +87,10 @@ void ZipInstaller::installStart()
// get the real file. // get the real file.
getter = new HttpGet(this); getter = new HttpGet(this);
getter->setProxy(m_proxy); getter->setProxy(m_proxy);
if(m_cache.exists()) {
getter->setCache(m_cache);
qDebug() << "installzip: setting cache to" << m_cache;
}
getter->setFile(downloadFile); getter->setFile(downloadFile);
getter->getFile(QUrl(m_url)); getter->getFile(QUrl(m_url));
@ -117,12 +122,13 @@ void ZipInstaller::downloadDone(bool error)
m_dp->setProgressMax(max); m_dp->setProgressMax(max);
} }
m_dp->setProgressValue(max); m_dp->setProgressValue(max);
if(getter->httpResponse() != 200) { if(getter->httpResponse() != 200 && !getter->isCached()) {
m_dp->addItem(tr("Download error: received HTTP error %1.").arg(getter->httpResponse()),LOGERROR); m_dp->addItem(tr("Download error: received HTTP error %1.").arg(getter->httpResponse()),LOGERROR);
m_dp->abort(); m_dp->abort();
emit done(true); emit done(true);
return; return;
} }
if(getter->isCached()) m_dp->addItem(tr("Cached file used."), LOGINFO);
if(error) { if(error) {
m_dp->addItem(tr("Download error: %1").arg(getter->errorString()),LOGERROR); m_dp->addItem(tr("Download error: %1").arg(getter->errorString()),LOGERROR);
m_dp->abort(); m_dp->abort();
@ -205,3 +211,4 @@ void ZipInstaller::updateDataReadProgress(int read, int total)
} }

View file

@ -46,6 +46,8 @@ public:
void setLogVersion(QStringList v) { m_verlist = v; qDebug() << m_verlist;} void setLogVersion(QStringList v) { m_verlist = v; qDebug() << m_verlist;}
void setUnzip(bool i) { m_unzip = i; } void setUnzip(bool i) { m_unzip = i; }
void setTarget(QString t) { m_target = t; } void setTarget(QString t) { m_target = t; }
void setCache(QDir c) { m_cache = c; };
void setCache(QString c) { m_cache = QDir(c); qDebug() << "!!!set cache:" << m_cache;}
signals: signals:
void done(bool error); void done(bool error);
@ -66,6 +68,7 @@ private:
bool m_unzip; bool m_unzip;
QString m_target; QString m_target;
int runner; int runner;
QDir m_cache;
HttpGet *getter; HttpGet *getter;
QTemporaryFile *downloadFile; QTemporaryFile *downloadFile;

View file

@ -128,11 +128,11 @@ void RbUtilQt::downloadInfo()
connect(daily, SIGNAL(done(bool)), this, SLOT(downloadDone(bool))); connect(daily, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
connect(daily, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool))); connect(daily, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
daily->setProxy(proxy()); daily->setProxy(proxy());
if(userSettings->value("defaults/offline").toBool())
daily->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
qDebug() << "downloading build info"; qDebug() << "downloading build info";
daily->setFile(&buildInfo); daily->setFile(&buildInfo);
daily->getFile(QUrl(devices->value("server_conf_url").toString())); daily->getFile(QUrl(devices->value("server_conf_url").toString()));
} }
@ -154,7 +154,8 @@ void RbUtilQt::downloadDone(bool error)
connect(bleeding, SIGNAL(done(bool)), this, SLOT(downloadBleedingDone(bool))); connect(bleeding, SIGNAL(done(bool)), this, SLOT(downloadBleedingDone(bool)));
connect(bleeding, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool))); connect(bleeding, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
bleeding->setProxy(proxy()); bleeding->setProxy(proxy());
if(userSettings->value("defaults/offline").toBool())
bleeding->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
bleeding->setFile(&bleedingInfo); bleeding->setFile(&bleedingInfo);
bleeding->getFile(QUrl(devices->value("bleeding_info").toString())); bleeding->getFile(QUrl(devices->value("bleeding_info").toString()));
} }
@ -462,6 +463,8 @@ bool RbUtilQt::installAuto()
installer->setProxy(proxy()); installer->setProxy(proxy());
installer->setLogSection("rockboxbase"); installer->setLogSection("rockboxbase");
installer->setLogVersion(myversion); installer->setLogVersion(myversion);
if(!userSettings->value("defaults/cachedisable").toBool())
installer->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
installer->setMountPoint(userSettings->value("defaults/mountpoint").toString()); installer->setMountPoint(userSettings->value("defaults/mountpoint").toString());
installer->install(logger); installer->install(logger);
@ -623,6 +626,8 @@ void RbUtilQt::installFonts()
installer->setLogSection("Fonts"); installer->setLogSection("Fonts");
installer->setLogVersion(versmap.value("arch_date")); installer->setLogVersion(versmap.value("arch_date"));
installer->setMountPoint(userSettings->value("defaults/mountpoint").toString()); installer->setMountPoint(userSettings->value("defaults/mountpoint").toString());
if(!userSettings->value("defaults/cachedisable").toBool())
installer->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
installer->install(logger); installer->install(logger);
} }
@ -651,6 +656,8 @@ void RbUtilQt::installVoice()
installer->setLogVersion(versmap.value("arch_date")); installer->setLogVersion(versmap.value("arch_date"));
installer->setMountPoint(userSettings->value("defaults/mountpoint").toString()); installer->setMountPoint(userSettings->value("defaults/mountpoint").toString());
installer->setTarget("/.rockbox/langs/english.voice"); installer->setTarget("/.rockbox/langs/english.voice");
if(!userSettings->value("defaults/cachedisable").toBool())
installer->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
installer->install(logger); installer->install(logger);
//connect(installer, SIGNAL(done(bool)), this, SLOT(done(bool))); //connect(installer, SIGNAL(done(bool)), this, SLOT(done(bool)));
@ -684,6 +691,8 @@ void RbUtilQt::installDoom()
installer->setLogSection("Game Addons"); installer->setLogSection("Game Addons");
installer->setLogVersion(versmap.value("arch_date")); installer->setLogVersion(versmap.value("arch_date"));
installer->setMountPoint(userSettings->value("defaults/mountpoint").toString()); installer->setMountPoint(userSettings->value("defaults/mountpoint").toString());
if(!userSettings->value("defaults/cachedisable").toBool())
installer->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
installer->install(logger); installer->install(logger);
} }
@ -783,6 +792,8 @@ void RbUtilQt::downloadManual(void)
logger->show(); logger->show();
installer = new ZipInstaller(this); installer = new ZipInstaller(this);
installer->setMountPoint(userSettings->value("defaults/mountpoint").toString()); installer->setMountPoint(userSettings->value("defaults/mountpoint").toString());
if(!userSettings->value("defaults/cachedisable").toBool())
installer->setCache(userSettings->value("defaults/cachepath", QDir::tempPath()).toString());
installer->setProxy(proxy()); installer->setProxy(proxy());
installer->setLogSection(section); installer->setLogSection(section);
installer->setUrl(manualurl); installer->setUrl(manualurl);