Change DB name to stella, add migration for old stellarc file.

This commit is contained in:
Christian Speckner 2021-01-02 15:45:35 +01:00
parent 08cb68fea9
commit 2e25d20554
14 changed files with 123 additions and 53 deletions

View File

@ -34,6 +34,7 @@ MODULE_OBJS := \
src/common/sdl_blitter/BlitterFactory.o \
src/common/repository/KeyValueRepositoryPropertyFile.o \
src/common/repository/KeyValueRepositoryJsonFile.o \
src/common/repository/KeyValueRepositoryConfigfile.o \
src/common/repository/CompositeKVRJsonAdapter.o
MODULE_DIRS += \

View File

@ -23,11 +23,6 @@
#include "Variant.hxx"
#include "bspf.hxx"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Woverloaded-virtual"
#endif
class KeyValueRepositoryAtomic;
class KeyValueRepository
@ -45,6 +40,8 @@ class KeyValueRepository
class KeyValueRepositoryAtomic : public KeyValueRepository {
public:
using KeyValueRepository::save;
virtual bool has(const string& key) = 0;
virtual bool get(const string& key, string& value) = 0;
@ -56,8 +53,4 @@ class KeyValueRepositoryAtomic : public KeyValueRepository {
KeyValueRepositoryAtomic* atomic() override { return this; }
};
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#endif // KEY_VALUE_REPOSITORY_HXX

View File

@ -20,29 +20,17 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
KeyValueRepositoryConfigfile::KeyValueRepositoryConfigfile(const FilesystemNode& file)
: myFile{file}
{
}
: KeyValueRepositoryFile<KeyValueRepositoryConfigfile>(file)
{}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::map<string, Variant> KeyValueRepositoryConfigfile::load()
std::map<string, Variant> KeyValueRepositoryConfigfile::load(istream& in)
{
std::map<string, Variant> values;
string line, key, value;
string::size_type equalPos, garbage;
stringstream in;
try
{
myFile.read(in);
}
catch(...)
{
Logger::error("ERROR: Couldn't load from settings file " + myFile.getShortPath());
return values;
}
while(getline(in, line))
{
// Strip all whitespace and tabs from the line
@ -72,9 +60,8 @@ std::map<string, Variant> KeyValueRepositoryConfigfile::load()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool KeyValueRepositoryConfigfile::save(const std::map<string, Variant>& values)
bool KeyValueRepositoryConfigfile::save(ostream& out, const std::map<string, Variant>& values)
{
stringstream out;
out << "; Stella configuration file" << endl
<< ";" << endl
<< "; Lines starting with ';' are comments and are ignored." << endl
@ -93,17 +80,4 @@ bool KeyValueRepositoryConfigfile::save(const std::map<string, Variant>& values)
// Write out each of the key and value pairs
for(const auto& [key, value]: values)
out << key << " = " << value << endl;
try
{
myFile.write(out);
return true;
}
catch(...)
{
Logger::error("ERROR: Couldn't save to settings file " + myFile.getShortPath());
return false;
}
}

View File

@ -19,21 +19,19 @@
#define KEY_VALUE_REPOSITORY_CONFIGFILE_HXX
#include "FSNode.hxx"
#include "KeyValueRepository.hxx"
#include "repository/KeyValueRepositoryFile.hxx"
class KeyValueRepositoryConfigfile : public KeyValueRepositoryAtomic
class KeyValueRepositoryConfigfile : public KeyValueRepositoryFile<KeyValueRepositoryConfigfile>
{
public:
using KeyValueRepositoryFile<KeyValueRepositoryConfigfile>::load;
using KeyValueRepositoryFile<KeyValueRepositoryConfigfile>::save;
explicit KeyValueRepositoryConfigfile(const FilesystemNode& file);
KeyValueRepositoryConfigfile(const FilesystemNode& node);
std::map<string, Variant> load() override;
static std::map<string, Variant> load(istream& in);
bool save(const std::map<string, Variant>& values) override;
private:
FilesystemNode myFile;
static bool save(ostream& out, const std::map<string, Variant>& values);
};
#endif // KEY_VALUE_REPOSITORY_CONFIGFILE_HXX

View File

@ -26,6 +26,9 @@
class KeyValueRepositoryJsonFile : public KeyValueRepositoryFile<KeyValueRepositoryJsonFile> {
public:
using KeyValueRepositoryFile<KeyValueRepositoryJsonFile>::load;
using KeyValueRepositoryFile<KeyValueRepositoryJsonFile>::save;
KeyValueRepositoryJsonFile(const FilesystemNode& node);
static std::map<string, Variant> load(istream& in);

View File

@ -26,6 +26,9 @@
class KeyValueRepositoryPropertyFile : public KeyValueRepositoryFile<KeyValueRepositoryPropertyFile> {
public:
using KeyValueRepositoryFile<KeyValueRepositoryPropertyFile>::load;
using KeyValueRepositoryFile<KeyValueRepositoryPropertyFile>::save;
KeyValueRepositoryPropertyFile(const FilesystemNode& node);
static std::map<string, Variant> load(istream& in);

View File

@ -15,13 +15,22 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include <sstream>
#include "SettingsDb.hxx"
#include "Logger.hxx"
#include "SqliteError.hxx"
#include "repository/KeyValueRepositoryNoop.hxx"
#include "repository/CompositeKeyValueRepositoryNoop.hxx"
#include "repository/CompositeKVRJsonAdapter.hxx"
#include "repository/KeyValueRepositoryConfigfile.hxx"
#include "KeyValueRepositorySqlite.hxx"
#include "SqliteTransaction.hxx"
#include "FSNode.hxx"
namespace {
constexpr Int32 CURRENT_VERSION = 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SettingsDb::SettingsDb(const string& databaseDirectory, const string& databaseName)
@ -46,14 +55,57 @@ void SettingsDb::initialize()
myPropertyRepositoryHost = std::move(propertyRepositoryHost);
myPropertyRepository = make_unique<CompositeKVRJsonAdapter>(*myPropertyRepositoryHost);
if (myDb->getUserVersion() == 0) {
initializeDb();
} else {
migrate();
}
}
catch (const SqliteError& err) {
Logger::error("sqlite DB " + databaseFileName() + " failed to initialize: " + err.what());
myDb.reset();
myPropertyRepositoryHost.reset();
mySettingsRepository = make_unique<KeyValueRepositoryNoop>();
myPropertyRepository = make_unique<CompositeKeyValueRepositoryNoop>();
myDb.reset();
myPropertyRepositoryHost.reset();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SettingsDb::initializeDb() {
SqliteTransaction tx{*myDb};
FilesystemNode legacyConfigFile{myDatabaseDirectory};
legacyConfigFile /= "stellarc";
FilesystemNode legacyConfigDatabase{myDatabaseDirectory};
legacyConfigDatabase /= "settings.sqlite3";
if (legacyConfigFile.exists() && legacyConfigFile.isFile()) {
Logger::info("importing old settings from " + legacyConfigFile.getPath());
mySettingsRepository->save(KeyValueRepositoryConfigfile{legacyConfigFile}.load());
}
myDb->setUserVersion(CURRENT_VERSION);
tx.commit();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SettingsDb::migrate() {
Int32 version = myDb->getUserVersion();
switch (version) {
case 1:
return;
default: {
stringstream ss;
ss << "invalid database version " << version;
throw new SqliteError(ss.str());
}
}
}

View File

@ -31,12 +31,18 @@ class SettingsDb
void initialize();
KeyValueRepository& settingsRepository() const { return *mySettingsRepository; }
KeyValueRepositoryAtomic& settingsRepository() const { return *mySettingsRepository; }
CompositeKeyValueRepository& propertyRepository() const { return *myPropertyRepository; }
const string& databaseFileName() const { return myDatabaseName; }
private:
void initializeDb();
void migrate();
private:
string myDatabaseDirectory;

View File

@ -20,6 +20,7 @@
#include "SqliteDatabase.hxx"
#include "Logger.hxx"
#include "SqliteError.hxx"
#include "SqliteStatement.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SqliteDatabase::SqliteDatabase(const string& databaseDirectory,
@ -91,3 +92,24 @@ void SqliteDatabase::exec(const string& sql) const
if (sqlite3_exec(myHandle, sql.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK)
throw SqliteError(myHandle);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 SqliteDatabase::getUserVersion() const
{
SqliteStatement stmt(*this, "PRAGMA user_version");
stmt.reset();
if (!stmt.step())
throw SqliteError("failed to get user_version");
return stmt.columnInt(0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void SqliteDatabase::setUserVersion(Int32 version) const
{
SqliteStatement stmt(*this, "PRAGMA user_version = %i", static_cast<int>(version));
stmt.reset();
stmt.step();
}

View File

@ -41,6 +41,9 @@ class SqliteDatabase
template<class T, class ...Ts>
void exec(const string& sql, T arg1, Ts... args) const;
Int32 getUserVersion() const;
void setUserVersion(Int32 version) const;
private:
string myDatabaseFile;

View File

@ -50,6 +50,15 @@ SqliteStatement& SqliteStatement::bind(int index, const string& value)
return *this;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SqliteStatement& SqliteStatement::bind(int index, Int32 value)
{
if (sqlite3_bind_int(myStmt, index, value) != SQLITE_OK)
throw SqliteError(myHandle);
return *this;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool SqliteStatement::step() const
{

View File

@ -35,6 +35,7 @@ class SqliteStatement {
operator sqlite3_stmt*() const { return myStmt; }
SqliteStatement& bind(int index, const string& value);
SqliteStatement& bind(int index, Int32 value);
bool step() const;

View File

@ -22,6 +22,11 @@
SqliteTransaction::SqliteTransaction(SqliteDatabase& db)
: myDb{db}
{
if (sqlite3_get_autocommit(db)) {
myTransactionClosed = true;
return;
}
myDb.exec("BEGIN TRANSACTION");
}

View File

@ -223,7 +223,7 @@ void OSystem::loadConfig(const Settings::Options& options)
if(!myHomeDir.isDirectory())
myHomeDir.makeDir();
mySettingsDb = make_shared<SettingsDb>(myBaseDir.getPath(), "settings");
mySettingsDb = make_shared<SettingsDb>(myBaseDir.getPath(), "stella");
mySettingsDb->initialize();
myConfigFile = FilesystemNode(mySettingsDb->databaseFileName());