mirror of https://github.com/stella-emu/stella.git
Change DB name to stella, add migration for old stellarc file.
This commit is contained in:
parent
08cb68fea9
commit
2e25d20554
|
@ -34,6 +34,7 @@ MODULE_OBJS := \
|
||||||
src/common/sdl_blitter/BlitterFactory.o \
|
src/common/sdl_blitter/BlitterFactory.o \
|
||||||
src/common/repository/KeyValueRepositoryPropertyFile.o \
|
src/common/repository/KeyValueRepositoryPropertyFile.o \
|
||||||
src/common/repository/KeyValueRepositoryJsonFile.o \
|
src/common/repository/KeyValueRepositoryJsonFile.o \
|
||||||
|
src/common/repository/KeyValueRepositoryConfigfile.o \
|
||||||
src/common/repository/CompositeKVRJsonAdapter.o
|
src/common/repository/CompositeKVRJsonAdapter.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
|
|
|
@ -23,11 +23,6 @@
|
||||||
#include "Variant.hxx"
|
#include "Variant.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Woverloaded-virtual"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class KeyValueRepositoryAtomic;
|
class KeyValueRepositoryAtomic;
|
||||||
|
|
||||||
class KeyValueRepository
|
class KeyValueRepository
|
||||||
|
@ -45,6 +40,8 @@ class KeyValueRepository
|
||||||
|
|
||||||
class KeyValueRepositoryAtomic : public KeyValueRepository {
|
class KeyValueRepositoryAtomic : public KeyValueRepository {
|
||||||
public:
|
public:
|
||||||
|
using KeyValueRepository::save;
|
||||||
|
|
||||||
virtual bool has(const string& key) = 0;
|
virtual bool has(const string& key) = 0;
|
||||||
|
|
||||||
virtual bool get(const string& key, string& value) = 0;
|
virtual bool get(const string& key, string& value) = 0;
|
||||||
|
@ -56,8 +53,4 @@ class KeyValueRepositoryAtomic : public KeyValueRepository {
|
||||||
KeyValueRepositoryAtomic* atomic() override { return this; }
|
KeyValueRepositoryAtomic* atomic() override { return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // KEY_VALUE_REPOSITORY_HXX
|
#endif // KEY_VALUE_REPOSITORY_HXX
|
||||||
|
|
|
@ -20,29 +20,17 @@
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
KeyValueRepositoryConfigfile::KeyValueRepositoryConfigfile(const FilesystemNode& file)
|
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;
|
std::map<string, Variant> values;
|
||||||
|
|
||||||
string line, key, value;
|
string line, key, value;
|
||||||
string::size_type equalPos, garbage;
|
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))
|
while(getline(in, line))
|
||||||
{
|
{
|
||||||
// Strip all whitespace and tabs from the 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
|
out << "; Stella configuration file" << endl
|
||||||
<< ";" << endl
|
<< ";" << endl
|
||||||
<< "; Lines starting with ';' are comments and are ignored." << 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
|
// Write out each of the key and value pairs
|
||||||
for(const auto& [key, value]: values)
|
for(const auto& [key, value]: values)
|
||||||
out << key << " = " << value << endl;
|
out << key << " = " << value << endl;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
myFile.write(out);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
Logger::error("ERROR: Couldn't save to settings file " + myFile.getShortPath());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,21 +19,19 @@
|
||||||
#define KEY_VALUE_REPOSITORY_CONFIGFILE_HXX
|
#define KEY_VALUE_REPOSITORY_CONFIGFILE_HXX
|
||||||
|
|
||||||
#include "FSNode.hxx"
|
#include "FSNode.hxx"
|
||||||
#include "KeyValueRepository.hxx"
|
#include "repository/KeyValueRepositoryFile.hxx"
|
||||||
|
|
||||||
class KeyValueRepositoryConfigfile : public KeyValueRepositoryAtomic
|
class KeyValueRepositoryConfigfile : public KeyValueRepositoryFile<KeyValueRepositoryConfigfile>
|
||||||
{
|
{
|
||||||
public:
|
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;
|
static bool save(ostream& out, const std::map<string, Variant>& values);
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
FilesystemNode myFile;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEY_VALUE_REPOSITORY_CONFIGFILE_HXX
|
#endif // KEY_VALUE_REPOSITORY_CONFIGFILE_HXX
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
|
|
||||||
class KeyValueRepositoryJsonFile : public KeyValueRepositoryFile<KeyValueRepositoryJsonFile> {
|
class KeyValueRepositoryJsonFile : public KeyValueRepositoryFile<KeyValueRepositoryJsonFile> {
|
||||||
public:
|
public:
|
||||||
|
using KeyValueRepositoryFile<KeyValueRepositoryJsonFile>::load;
|
||||||
|
using KeyValueRepositoryFile<KeyValueRepositoryJsonFile>::save;
|
||||||
|
|
||||||
KeyValueRepositoryJsonFile(const FilesystemNode& node);
|
KeyValueRepositoryJsonFile(const FilesystemNode& node);
|
||||||
|
|
||||||
static std::map<string, Variant> load(istream& in);
|
static std::map<string, Variant> load(istream& in);
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
|
|
||||||
class KeyValueRepositoryPropertyFile : public KeyValueRepositoryFile<KeyValueRepositoryPropertyFile> {
|
class KeyValueRepositoryPropertyFile : public KeyValueRepositoryFile<KeyValueRepositoryPropertyFile> {
|
||||||
public:
|
public:
|
||||||
|
using KeyValueRepositoryFile<KeyValueRepositoryPropertyFile>::load;
|
||||||
|
using KeyValueRepositoryFile<KeyValueRepositoryPropertyFile>::save;
|
||||||
|
|
||||||
KeyValueRepositoryPropertyFile(const FilesystemNode& node);
|
KeyValueRepositoryPropertyFile(const FilesystemNode& node);
|
||||||
|
|
||||||
static std::map<string, Variant> load(istream& in);
|
static std::map<string, Variant> load(istream& in);
|
||||||
|
|
|
@ -15,13 +15,22 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include "SettingsDb.hxx"
|
#include "SettingsDb.hxx"
|
||||||
#include "Logger.hxx"
|
#include "Logger.hxx"
|
||||||
#include "SqliteError.hxx"
|
#include "SqliteError.hxx"
|
||||||
#include "repository/KeyValueRepositoryNoop.hxx"
|
#include "repository/KeyValueRepositoryNoop.hxx"
|
||||||
#include "repository/CompositeKeyValueRepositoryNoop.hxx"
|
#include "repository/CompositeKeyValueRepositoryNoop.hxx"
|
||||||
#include "repository/CompositeKVRJsonAdapter.hxx"
|
#include "repository/CompositeKVRJsonAdapter.hxx"
|
||||||
|
#include "repository/KeyValueRepositoryConfigfile.hxx"
|
||||||
#include "KeyValueRepositorySqlite.hxx"
|
#include "KeyValueRepositorySqlite.hxx"
|
||||||
|
#include "SqliteTransaction.hxx"
|
||||||
|
#include "FSNode.hxx"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
constexpr Int32 CURRENT_VERSION = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
SettingsDb::SettingsDb(const string& databaseDirectory, const string& databaseName)
|
SettingsDb::SettingsDb(const string& databaseDirectory, const string& databaseName)
|
||||||
|
@ -46,14 +55,57 @@ void SettingsDb::initialize()
|
||||||
myPropertyRepositoryHost = std::move(propertyRepositoryHost);
|
myPropertyRepositoryHost = std::move(propertyRepositoryHost);
|
||||||
|
|
||||||
myPropertyRepository = make_unique<CompositeKVRJsonAdapter>(*myPropertyRepositoryHost);
|
myPropertyRepository = make_unique<CompositeKVRJsonAdapter>(*myPropertyRepositoryHost);
|
||||||
|
|
||||||
|
if (myDb->getUserVersion() == 0) {
|
||||||
|
initializeDb();
|
||||||
|
} else {
|
||||||
|
migrate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (const SqliteError& err) {
|
catch (const SqliteError& err) {
|
||||||
Logger::error("sqlite DB " + databaseFileName() + " failed to initialize: " + err.what());
|
Logger::error("sqlite DB " + databaseFileName() + " failed to initialize: " + err.what());
|
||||||
|
|
||||||
myDb.reset();
|
|
||||||
myPropertyRepositoryHost.reset();
|
|
||||||
|
|
||||||
mySettingsRepository = make_unique<KeyValueRepositoryNoop>();
|
mySettingsRepository = make_unique<KeyValueRepositoryNoop>();
|
||||||
myPropertyRepository = make_unique<CompositeKeyValueRepositoryNoop>();
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,18 @@ class SettingsDb
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|
||||||
KeyValueRepository& settingsRepository() const { return *mySettingsRepository; }
|
KeyValueRepositoryAtomic& settingsRepository() const { return *mySettingsRepository; }
|
||||||
|
|
||||||
CompositeKeyValueRepository& propertyRepository() const { return *myPropertyRepository; }
|
CompositeKeyValueRepository& propertyRepository() const { return *myPropertyRepository; }
|
||||||
|
|
||||||
const string& databaseFileName() const { return myDatabaseName; }
|
const string& databaseFileName() const { return myDatabaseName; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void initializeDb();
|
||||||
|
|
||||||
|
void migrate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
string myDatabaseDirectory;
|
string myDatabaseDirectory;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "SqliteDatabase.hxx"
|
#include "SqliteDatabase.hxx"
|
||||||
#include "Logger.hxx"
|
#include "Logger.hxx"
|
||||||
#include "SqliteError.hxx"
|
#include "SqliteError.hxx"
|
||||||
|
#include "SqliteStatement.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
SqliteDatabase::SqliteDatabase(const string& databaseDirectory,
|
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)
|
if (sqlite3_exec(myHandle, sql.c_str(), nullptr, nullptr, nullptr) != SQLITE_OK)
|
||||||
throw SqliteError(myHandle);
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ class SqliteDatabase
|
||||||
template<class T, class ...Ts>
|
template<class T, class ...Ts>
|
||||||
void exec(const string& sql, T arg1, Ts... args) const;
|
void exec(const string& sql, T arg1, Ts... args) const;
|
||||||
|
|
||||||
|
Int32 getUserVersion() const;
|
||||||
|
void setUserVersion(Int32 version) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
string myDatabaseFile;
|
string myDatabaseFile;
|
||||||
|
|
|
@ -50,6 +50,15 @@ SqliteStatement& SqliteStatement::bind(int index, const string& value)
|
||||||
return *this;
|
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
|
bool SqliteStatement::step() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,7 @@ class SqliteStatement {
|
||||||
operator sqlite3_stmt*() const { return myStmt; }
|
operator sqlite3_stmt*() const { return myStmt; }
|
||||||
|
|
||||||
SqliteStatement& bind(int index, const string& value);
|
SqliteStatement& bind(int index, const string& value);
|
||||||
|
SqliteStatement& bind(int index, Int32 value);
|
||||||
|
|
||||||
bool step() const;
|
bool step() const;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,11 @@
|
||||||
SqliteTransaction::SqliteTransaction(SqliteDatabase& db)
|
SqliteTransaction::SqliteTransaction(SqliteDatabase& db)
|
||||||
: myDb{db}
|
: myDb{db}
|
||||||
{
|
{
|
||||||
|
if (sqlite3_get_autocommit(db)) {
|
||||||
|
myTransactionClosed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
myDb.exec("BEGIN TRANSACTION");
|
myDb.exec("BEGIN TRANSACTION");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,7 @@ void OSystem::loadConfig(const Settings::Options& options)
|
||||||
if(!myHomeDir.isDirectory())
|
if(!myHomeDir.isDirectory())
|
||||||
myHomeDir.makeDir();
|
myHomeDir.makeDir();
|
||||||
|
|
||||||
mySettingsDb = make_shared<SettingsDb>(myBaseDir.getPath(), "settings");
|
mySettingsDb = make_shared<SettingsDb>(myBaseDir.getPath(), "stella");
|
||||||
mySettingsDb->initialize();
|
mySettingsDb->initialize();
|
||||||
myConfigFile = FilesystemNode(mySettingsDb->databaseFileName());
|
myConfigFile = FilesystemNode(mySettingsDb->databaseFileName());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue