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/repository/KeyValueRepositoryPropertyFile.o \
|
||||
src/common/repository/KeyValueRepositoryJsonFile.o \
|
||||
src/common/repository/KeyValueRepositoryConfigfile.o \
|
||||
src/common/repository/CompositeKVRJsonAdapter.o
|
||||
|
||||
MODULE_DIRS += \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -22,6 +22,11 @@
|
|||
SqliteTransaction::SqliteTransaction(SqliteDatabase& db)
|
||||
: myDb{db}
|
||||
{
|
||||
if (sqlite3_get_autocommit(db)) {
|
||||
myTransactionClosed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
myDb.exec("BEGIN TRANSACTION");
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
Loading…
Reference in New Issue