HaikuDepot: Drop Caches on Version Change

To avoid having to upgrade cache-data formats,
drop the caches when the application starts with
a different version from last time the
application launches.

Change-Id: I2f5b831b6a4fc570457bc633fd440a9021648b02
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3749
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
This commit is contained in:
Andrew Lindesay 2021-02-22 21:05:49 +13:00
parent 00fda04592
commit 02ccdc6fa1
7 changed files with 165 additions and 45 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2017-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@ -8,7 +8,6 @@
#include <stdlib.h>
#include <pthread.h>
#include <AppFileInfo.h>
#include <Application.h>
#include <Autolock.h>
#include <NetworkInterface.h>
@ -16,6 +15,7 @@
#include <Roster.h>
#include <Url.h>
#include "AppUtils.h"
#include "Logger.h"
@ -80,35 +80,11 @@ ServerSettings::_InitUserAgent()
const BString
ServerSettings::_GetUserAgentVersionString()
{
app_info info;
if (be_app->GetAppInfo(&info) != B_OK) {
HDERROR("Unable to get the application info");
be_app->Quit();
return BString(USERAGENT_FALLBACK_VERSION);
}
BFile file(&info.ref, B_READ_ONLY);
if (file.InitCheck() != B_OK) {
HDERROR("Unable to access the application info file");
be_app->Quit();
return BString(USERAGENT_FALLBACK_VERSION);
}
BAppFileInfo appFileInfo(&file);
version_info versionInfo;
if (appFileInfo.GetVersionInfo(
&versionInfo, B_APP_VERSION_KIND) != B_OK) {
HDERROR("Unable to establish the application version");
be_app->Quit();
return BString(USERAGENT_FALLBACK_VERSION);
}
BString result;
result.SetToFormat("%" B_PRId32 ".%" B_PRId32 ".%" B_PRId32,
versionInfo.major, versionInfo.middle, versionInfo.minor);
if (AppUtils::GetAppVersionString(result) != B_OK) {
be_app->Quit();
return BString(USERAGENT_FALLBACK_VERSION);
}
return result;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2017-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@ -23,6 +23,7 @@
#include "support.h"
#include "AppUtils.h"
#include "FeaturedPackagesView.h"
#include "Logger.h"
#include "MainWindow.h"
@ -87,12 +88,13 @@ App::ReadyToRun()
BMessage settings;
_LoadSettings(settings);
if (!_CheckTestFile())
{
if (!_CheckTestFile()) {
Quit();
return;
}
_ClearCacheOnVersionChange();
fMainWindow = new MainWindow(settings);
_ShowWindow(fMainWindow);
}
@ -582,3 +584,62 @@ App::_CheckTestFile()
return true;
}
/*! This method will check to see if the version of the application has changed.
If it has changed then it will delete all of the contents of the cache
directory. This will mean that when application logic changes, it need not
bother to migrate the cached files. Also any old cached files will be
cleared out that no longer serve any purpose.
Errors arising in this logic need not prevent the application from failing
to start as this is just a clean-up.
*/
void
App::_ClearCacheOnVersionChange()
{
BString version;
if (AppUtils::GetAppVersionString(version) != B_OK) {
HDERROR("clear cache; unable to get the application version");
return;
}
BPath lastVersionPath;
if (StorageUtils::LocalWorkingFilesPath(
"version.txt", lastVersionPath) != B_OK) {
HDERROR("clear cache; unable to get version file path");
return;
}
bool exists;
off_t size;
if (StorageUtils::ExistsObject(
lastVersionPath, &exists, NULL, &size) != B_OK) {
HDERROR("clear cache; unable to check version file exists");
return;
}
BString lastVersion;
if (exists && StorageUtils::AppendToString(lastVersionPath, lastVersion)
!= B_OK) {
HDERROR("clear cache; unable to read the version from [%s]",
lastVersionPath.Path());
return;
}
if (lastVersion != version) {
HDINFO("last version [%s] and current version [%s] do not match"
" -> will flush cache", lastVersion.String(), version.String());
StorageUtils::RemoveWorkingDirectoryContents();
HDINFO("will write version [%s] to [%s]",
version.String(), lastVersionPath.Path());
StorageUtils::AppendToFile(version, lastVersionPath);
} else {
HDINFO("last version [%s] and current version [%s] match"
" -> cache retained", lastVersion.String(), version.String());
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2013, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2018-2020, Andrew Lindesay <apl@lindesay.co.nz>
* Copyright 2018-2021, Andrew Lindesay <apl@lindesay.co.nz>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef APP_H
@ -40,6 +40,7 @@ private:
bool _CheckTestFile();
static bool _CheckIsFirstRun();
void _ClearCacheOnVersionChange();
private:
MainWindow* fMainWindow;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018-2020, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2018-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@ -8,8 +8,10 @@
#include <string.h>
#include <AppFileInfo.h>
#include <Application.h>
#include <MenuItem.h>
#include <Roster.h>
#include <String.h>
#include "HaikuDepotConstants.h"
@ -86,3 +88,36 @@ AppUtils::GetCodeAtIndexInMenu(BMenu* menu, int32 index, BString* result)
return B_ERROR;
return itemMessage->FindString("code", result);
}
/*static*/ status_t
AppUtils::GetAppVersionString(BString& result)
{
app_info info;
if (be_app->GetAppInfo(&info) != B_OK) {
HDERROR("Unable to get the application info");
return B_ERROR;
}
BFile file(&info.ref, B_READ_ONLY);
if (file.InitCheck() != B_OK) {
HDERROR("Unable to access the application info file");
return B_ERROR;
}
BAppFileInfo appFileInfo(&file);
version_info versionInfo;
if (appFileInfo.GetVersionInfo(
&versionInfo, B_APP_VERSION_KIND) != B_OK) {
HDERROR("Unable to establish the application version");
return B_ERROR;
}
result.SetToFormat("%" B_PRId32 ".%" B_PRId32 ".%" B_PRId32,
versionInfo.major, versionInfo.middle, versionInfo.minor);
return B_OK;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018-2020, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2018-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef APP_UTILS_H
@ -22,6 +22,8 @@ public:
static int32 IndexOfCodeInMenu(const BString& code, BMenu* menu);
static status_t GetCodeAtIndexInMenu(BMenu* menu, int32 index,
BString* result);
static status_t GetAppVersionString(BString& result);
};

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2017-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@ -41,8 +41,8 @@ StorageUtils::SetWorkingFilesUnavailable()
* string provided.
*/
status_t
StorageUtils::AppendToString(BPath& path, BString& result)
/*static*/ status_t
StorageUtils::AppendToString(const BPath& path, BString& result)
{
BFile file(path.Path(), O_RDONLY);
uint8_t buffer[FILE_TO_STRING_BUFFER_LEN];
@ -55,6 +55,46 @@ StorageUtils::AppendToString(BPath& path, BString& result)
}
/*static*/ status_t
StorageUtils::AppendToFile(const BString& input, const BPath& path)
{
BFile file(path.Path(), O_WRONLY | O_CREAT | O_APPEND);
const char* cstr = input.String();
size_t cstrLen = strlen(cstr);
return file.WriteExactly(cstr, cstrLen);
}
/*static*/ status_t
StorageUtils::RemoveWorkingDirectoryContents()
{
BPath path;
status_t result = B_OK;
if (result == B_OK)
result = find_directory(B_USER_CACHE_DIRECTORY, &path);
if (result == B_OK)
result = path.Append(CACHE_DIRECTORY_APP);
bool exists;
bool isDirectory;
if (result == B_OK)
result = ExistsObject(path, &exists, &isDirectory, NULL);
if (result == B_OK && exists && !isDirectory) {
HDERROR("the working directory at [%s] is not a directory",
path.Path());
result = B_ERROR;
}
if (result == B_OK && exists)
result = RemoveDirectoryContents(path);
return result;
}
/* This method will traverse the directory structure and will remove all of the
* files that are present in the directories as well as the directories
* themselves.
@ -85,9 +125,10 @@ StorageUtils::RemoveDirectoryContents(BPath& path)
if (isDirectory)
RemoveDirectoryContents(directoryEntryPath);
if (remove(directoryEntryPath.Path()) == 0)
HDDEBUG("did delete [%s]", directoryEntryPath.Path());
else {
if (remove(directoryEntryPath.Path()) == 0) {
HDDEBUG("did delete contents under [%s]",
directoryEntryPath.Path());
} else {
HDERROR("unable to delete [%s]", directoryEntryPath.Path());
result = B_ERROR;
}
@ -305,4 +346,4 @@ StorageUtils::SwapExtensionOnPathComponent(const char* pathComponent,
result.Append(".");
result.Append(extension);
return result;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>.
* Copyright 2017-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef PATH_UTILS_H
@ -22,8 +22,12 @@ public:
static status_t CheckCanWriteTo(const BPath& path);
static status_t AppendToString(const BPath& path, BString& result);
static status_t AppendToFile(const BString& input,
const BPath& path);
static status_t RemoveWorkingDirectoryContents();
static status_t RemoveDirectoryContents(BPath& path);
static status_t AppendToString(BPath& path, BString& result);
static status_t ExistsObject(const BPath& path,
bool* exists,
bool* isDirectory,