1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Auto-update: Better resuming support, lockfree-threading

This commit is contained in:
Tux3 / Mlkj / !Lev.uXFMLA 2015-01-27 00:24:42 +01:00
parent 4907661752
commit d80c1ee8ac
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
2 changed files with 52 additions and 13 deletions

View File

@ -65,9 +65,13 @@ const QString AutoUpdater::checkURI = AutoUpdater::updateServer+"/qtox/"+AutoUpd
const QString AutoUpdater::flistURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/flist";
const QString AutoUpdater::filesURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/files/";
bool AutoUpdater::abortFlag{false};
std::atomic_bool AutoUpdater::isDownloadingUpdate{false};
bool AutoUpdater::isUpdateAvailable()
{
if (isDownloadingUpdate)
return false;
VersionInfo newVersion = getUpdateVersion();
if (newVersion.timestamp <= TIMESTAMP
|| newVersion.versionString.isEmpty() || newVersion.versionString == GIT_VERSION)
@ -280,26 +284,33 @@ bool AutoUpdater::downloadUpdate()
if (platform.isEmpty())
return false;
bool expectFalse = false;
if (!isDownloadingUpdate.compare_exchange_strong(expectFalse,true))
return false;
// Get a list of files to update
QByteArray newFlistData = getUpdateFlist();
QList<UpdateFileMeta> newFlist = parseFlist(newFlistData);
QList<UpdateFileMeta> diff = genUpdateDiff(newFlist);
if (abortFlag)
{
isDownloadingUpdate = false;
return false;
}
qDebug() << "AutoUpdater: Need to update "<<diff.size()<<" files";
// Create an empty directory to download updates into
QString updateDirStr = Settings::getInstance().getSettingsDirPath() + "/update/";
QDir updateDir(updateDirStr);
if (updateDir.exists())
updateDir.removeRecursively();
QDir().mkdir(updateDirStr);
if (!updateDir.exists())
QDir().mkdir(updateDirStr);
updateDir = QDir(updateDirStr);
if (!updateDir.exists())
{
qWarning() << "AutoUpdater::downloadUpdate: Can't create update directory, aborting...";
isDownloadingUpdate = false;
return false;
}
@ -308,6 +319,7 @@ bool AutoUpdater::downloadUpdate()
if (!newFlistFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
qWarning() << "AutoUpdater::downloadUpdate: Can't save new flist file, aborting...";
isDownloadingUpdate = false;
return false;
}
newFlistFile.write(newFlistData);
@ -317,7 +329,19 @@ bool AutoUpdater::downloadUpdate()
for (UpdateFileMeta fileMeta : diff)
{
if (abortFlag)
{
isDownloadingUpdate = false;
return false;
}
// Skip files we already have
QFile fileFile(updateDirStr+fileMeta.installpath);
if (fileFile.open(QIODevice::ReadOnly) && fileFile.size() == (qint64)fileMeta.size)
{
qDebug() << "AutoUpdater: Skipping already downloaded file '"+fileMeta.installpath+"'";
fileFile.close();
continue;
}
qDebug() << "AutoUpdater: Downloading '"+fileMeta.installpath+"' ...";
@ -329,10 +353,14 @@ bool AutoUpdater::downloadUpdate()
// Download
UpdateFile file = getUpdateFile(fileMeta);
if (abortFlag)
{
isDownloadingUpdate = false;
return false;
}
if (file.data.isNull())
{
qWarning() << "AutoUpdater::downloadUpdate: Error downloading a file, aborting...";
isDownloadingUpdate = false;
return false;
}
@ -341,20 +369,24 @@ bool AutoUpdater::downloadUpdate()
file.data.size(), key) != 0)
{
qCritical() << "AutoUpdater: downloadUpdate: RECEIVED FORGED FILE, aborting...";
isDownloadingUpdate = false;
return false;
}
// Save
QFile fileFile(updateDirStr+fileMeta.installpath);
if (!fileFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
qWarning() << "AutoUpdater::downloadUpdate: Can't save new update file, aborting...";
isDownloadingUpdate = false;
return false;
}
fileFile.write(file.data);
fileFile.close();
}
qDebug() << "AutoUpdater::downloadUpdate: The update is ready, it'll be installed on the next restart";
isDownloadingUpdate = false;
return true;
}
@ -364,6 +396,9 @@ bool AutoUpdater::isLocalUpdateReady()
if (platform.isEmpty())
return false;
if (isDownloadingUpdate)
return false;
// Check that there's an update dir in the first place, valid or not
QString updateDirStr = Settings::getInstance().getSettingsDirPath() + "/update/";
QDir updateDir(updateDirStr);
@ -380,22 +415,15 @@ bool AutoUpdater::isLocalUpdateReady()
QList<UpdateFileMeta> updateFlist = parseFlist(updateFlistData);
QList<UpdateFileMeta> diff = genUpdateDiff(updateFlist);
// If the update wasn't downloaded correctly, redownload it
// We don't check signatures to not block qTox too long, the updater will do it anyway
// Check that we have every file
for (UpdateFileMeta fileMeta : diff)
{
if (!QFile::exists(updateDirStr+fileMeta.installpath))
{
QtConcurrent::run(&AutoUpdater::downloadUpdate);
return false;
}
QFile f(updateDirStr+fileMeta.installpath);
if (f.size() != (int64_t)fileMeta.size)
{
QtConcurrent::run(&AutoUpdater::downloadUpdate);
return false;
}
}
return true;
@ -446,6 +474,9 @@ fail:
void AutoUpdater::checkUpdatesAsyncInteractive()
{
if (isDownloadingUpdate)
return;
QtConcurrent::run(&AutoUpdater::checkUpdatesAsyncInteractiveWorker);
}
@ -454,7 +485,12 @@ void AutoUpdater::checkUpdatesAsyncInteractiveWorker()
if (!isUpdateAvailable())
return;
if (Widget::getInstance()->askMsgboxQuestion(QObject::tr("Update", "The title of a message box"),
// If there's already an update dir, resume updating, otherwise ask the user
QString updateDirStr = Settings::getInstance().getSettingsDirPath() + "/update/";
QDir updateDir(updateDirStr);
if ((updateDir.exists() && QFile(updateDirStr+"flist").exists())
|| Widget::getInstance()->askMsgboxQuestion(QObject::tr("Update", "The title of a message box"),
QObject::tr("An update is available, do you want to download it now?\nIt will be installed when qTox restarts.")))
{
downloadUpdate();
@ -464,4 +500,5 @@ void AutoUpdater::checkUpdatesAsyncInteractiveWorker()
void AutoUpdater::abortUpdates()
{
abortFlag = true;
isDownloadingUpdate = false;
}

View File

@ -21,6 +21,7 @@
#include <QString>
#include <QList>
#include <sodium.h>
#include <atomic>
/// For now we only support auto updates on Windows and OS X, although extending it is not a technical issue.
/// Linux users are expected to use their package managers or update manually through official channels.
@ -122,6 +123,7 @@ private:
static const QString updaterBin; ///< Path to the qtox-updater binary
static unsigned char key[];
static bool abortFlag; ///< If true, try to abort everything.
static std::atomic_bool isDownloadingUpdate; ///< We'll pretend there's no new update available if we're already updating
};
#endif // AUTOUPDATE_H