diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2016-09-09 08:51:25 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2016-09-09 15:00:58 +0200 |
commit | 6bc3fe31a3f354afc7be870a4a2d375ab6c746b6 (patch) | |
tree | 39b439b16cb872b3d982a6083a546456001d0f8e /migration | |
parent | cc6fc6577940df89c57db08743b181291c2a4b43 (diff) |
add support for migrations
They're run from the UI thread so can even be interactive.
Diffstat (limited to 'migration')
-rw-r--r-- | migration/20160906_0-mappings.cpp | 14 | ||||
-rw-r--r-- | migration/20160906_1-axis-signs.cpp | 0 | ||||
-rw-r--r-- | migration/CMakeLists.txt | 2 | ||||
-rw-r--r-- | migration/export.hpp | 28 | ||||
-rw-r--r-- | migration/migration.cpp | 129 | ||||
-rw-r--r-- | migration/migration.hpp | 72 |
6 files changed, 245 insertions, 0 deletions
diff --git a/migration/20160906_0-mappings.cpp b/migration/20160906_0-mappings.cpp new file mode 100644 index 00000000..0ff3095a --- /dev/null +++ b/migration/20160906_0-mappings.cpp @@ -0,0 +1,14 @@ +#include "migration.hpp" + +#include <QDebug> + +using namespace migrations; + +struct foo : migration +{ + const QString& unique_date() const override { qDebug() << "foo"; static QString ret(""); return ret; } + bool should_run() const override { qDebug() << "bar"; return false; } + bool run() override { return false; } +}; + +OPENTRACK_MIGRATION(foo); diff --git a/migration/20160906_1-axis-signs.cpp b/migration/20160906_1-axis-signs.cpp new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/migration/20160906_1-axis-signs.cpp diff --git a/migration/CMakeLists.txt b/migration/CMakeLists.txt new file mode 100644 index 00000000..d220b002 --- /dev/null +++ b/migration/CMakeLists.txt @@ -0,0 +1,2 @@ +opentrack_boilerplate(opentrack-migration BIN) +target_link_libraries(opentrack-migration opentrack-logic opentrack-spline-widget) diff --git a/migration/export.hpp b/migration/export.hpp new file mode 100644 index 00000000..800ddf35 --- /dev/null +++ b/migration/export.hpp @@ -0,0 +1,28 @@ +#pragma once + +#ifdef BUILD_migration +# ifdef _WIN32 +# define OPENTRACK_MIGRATION_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_MIGRATION_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_MIGRATION_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_MIGRATION_LINKAGE +# else +# define OPENTRACK_MIGRATION_EXPORT OPENTRACK_MIGRATION_LINKAGE +# endif + +#else + #ifdef _WIN32 + # define OPENTRACK_MIGRATION_LINKAGE __declspec(dllimport) + #else + # define OPENTRACK_MIGRATION_LINKAGE + #endif + + #ifndef _MSC_VER + # define OPENTRACK_MIGRATION_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_MIGRATION_LINKAGE + #else + # define OPENTRACK_MIGRATION_EXPORT OPENTRACK_MIGRATION_LINKAGE + #endif +#endif diff --git a/migration/migration.cpp b/migration/migration.cpp new file mode 100644 index 00000000..6e54de19 --- /dev/null +++ b/migration/migration.cpp @@ -0,0 +1,129 @@ +#include "migration.hpp" + +#include "options/options.hpp" +#include "compat/util.hpp" + +#include <QString> +#include <QSettings> +#include <QDebug> + +#include <memory> + +namespace migrations { + +namespace detail { + +void migrator::register_migration(migration* m) +{ + migrations().push_back(m); +} + +migrator::vec& migrator::migrations() +{ + static vec ret; + return ret; +} + +QString migrator::last_migration_time() +{ + QString ret; + + std::shared_ptr<QSettings> s(options::group::ini_file()); + + s->beginGroup("migrations"); + ret = s->value("last-migration-at", "19700101_00").toString(); + s->endGroup(); + + return ret; +} + +QString migrator::time_after_migrations() +{ + const vec list = sorted_migrations(); + + if (list.size() == 0u) + return QStringLiteral("19700101_00"); + + QString ret = list[list.size() - 1]->unique_date(); + ret += QStringLiteral("~"); + + return ret; +} + +void migrator::set_last_migration_time(const QString& val) +{ + std::shared_ptr<QSettings> s(options::group::ini_file()); + + s->beginGroup("migrations"); + s->setValue("last-migration-at", val); + s->endGroup(); +} + +migrator::vec migrator::sorted_migrations() +{ + vec list(migrations()); + std::sort(list.begin(), list.end(), [](const mm x, const mm y) { return x->unique_date() < y->unique_date(); }); + return list; +} + +std::vector<QString> migrator::run() +{ + vec migrations = sorted_migrations(); + vstr done; + + const QString last_migration = last_migration_time(); + + qDebug() << "migration: config" << options::group::ini_filename() << "time" << last_migration; + + for (migration* m_ : migrations) + { + migration& m(*m_); + + const QString date = m.unique_date(); + + if (date <= last_migration) + continue; + + if (m.should_run()) + { + m.run(); + done.push_back(m.name()); + } + } + + mark_config_as_not_needing_migration(); + + if (done.size()) + { + qDebug() << "migration: done" << done.size() << "units"; + for (const QString& name : done) + qDebug() << "--" << name; + qDebug() << ""; + } + + return done; +} + +} + +migration::migration() {} +migration::~migration() {} + +} // ns + +std::vector<QString> run_migrations() +{ + return migrations::detail::migrator::run(); +} + +void mark_config_as_not_needing_migration() +{ + using m = migrations::detail::migrator; + + m::mark_config_as_not_needing_migration(); +} + +void migrations::detail::migrator::mark_config_as_not_needing_migration() +{ + set_last_migration_time(time_after_migrations()); +} diff --git a/migration/migration.hpp b/migration/migration.hpp new file mode 100644 index 00000000..b9c20f15 --- /dev/null +++ b/migration/migration.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include <QString> +#include <vector> + +#include "export.hpp" + +namespace migrations { + +class migration; +class registrator; + +namespace detail { + class migrator final + { + using mm = migration*; + template<typename t> using vec_ = std::vector<t>; + using vstr = vec_<QString>; + using vec = vec_<mm>; + static vec& migrations(); + static QString last_migration_time(); + static QString time_after_migrations(); + static void set_last_migration_time(const QString& val); + migrator() = delete; + static vec sorted_migrations(); + public: + static vstr run(); + static void register_migration(migration* m); + static void mark_config_as_not_needing_migration(); + }; + + template<typename t> + struct registrator final + { + registrator() + { + static t m; + migrator::register_migration(static_cast<migration*>(&m)); + } + }; +} + +#ifndef __COUNTER__ +# error "oops, need __COUNTER__ extension for preprocessor" +#endif + +#define OPENTRACK_MIGRATION(type) static ::migrations::detail::registrator<type> opentrack_migration_registrator__ ## __COUNTER__ ## _gensym; + +#ifdef Q_CREATOR_RUN +# pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +class migration +{ + migration& operator=(const migration&) = delete; + migration(const migration&) = delete; + migration& operator=(migration&&) = delete; + migration(migration&&) = delete; + +public: + migration(); + virtual ~migration(); + virtual QString unique_date() const = 0; + virtual QString name() const = 0; + virtual bool should_run() const = 0; + virtual void run() = 0; +}; + +} + +OPENTRACK_MIGRATION_EXPORT std::vector<QString> run_migrations(); +OPENTRACK_MIGRATION_EXPORT void mark_config_as_not_needing_migration(); |