12#include <QSqlDatabase>
14#include <QtConcurrentRun>
26 const std::shared_ptr<ConsistencyChecker> Checker_;
28 explicit FailedImpl (std::shared_ptr<ConsistencyChecker> checker)
29 : Checker_ {
std::move (checker)}
35 return Checker_->DumpReinit ();
39 ConsistencyChecker::ConsistencyChecker (QString dbPath, QString dialogContext, QObject *parent)
41 , DBPath_ {
std::move (dbPath) }
42 , DialogContext_ {
std::move (dialogContext) }
48 return std::shared_ptr<ConsistencyChecker> {
new ConsistencyChecker { std::move (dbPath), std::move (dialogContext) } };
53 return QtConcurrent::run ([pThis = shared_from_this ()] {
return pThis->CheckDB (); });
58 qDebug () << Q_FUNC_INFO
63 std::shared_ptr<QSqlDatabase> db
65 new QSqlDatabase { QSqlDatabase::addDatabase (
"QSQLITE", connName) },
66 [connName] (QSqlDatabase *db)
69 QSqlDatabase::removeDatabase (connName);
73 db->setDatabaseName (DBPath_);
76 qWarning () << Q_FUNC_INFO
77 <<
"cannot open the DB, but that's not the kind of errors we're solving.";
81 QSqlQuery pragma { *db };
82 static const QString checkQuery = qgetenv (
"LC_THOROUGH_SQLITE_CHECK") ==
"1" ?
83 QStringLiteral (
"PRAGMA integrity_check;") :
84 QStringLiteral (
"PRAGMA quick_check;");
85 const auto isGood = pragma.exec (checkQuery) &&
87 pragma.value (0) ==
"ok";
88 qDebug () << Q_FUNC_INFO
96 return std::make_shared<FailedImpl> (shared_from_this ());
99 QFuture<ConsistencyChecker::DumpResult_t> ConsistencyChecker::DumpReinit ()
101 QFutureInterface<DumpResult_t> iface;
102 iface.reportStarted ();
104 DumpReinitImpl (iface);
106 return iface.future ();
111 void ReportResult (QFutureInterface<ConsistencyChecker::DumpResult_t> iface,
114 iface.reportFinished (&result);
118 void ConsistencyChecker::DumpReinitImpl (QFutureInterface<DumpResult_t> iface)
120 const QFileInfo fi { DBPath_ };
121 const auto filesize = fi.size ();
127 qDebug () << Q_FUNC_INFO
128 <<
"db size:" << filesize
129 <<
"free space:" << available;
130 if (available >=
static_cast<quint64
> (filesize))
133 if (QMessageBox::question (
nullptr,
135 tr (
"Not enough available space on partition with file %1: "
136 "%2 while the restored file is expected to be around %3. "
137 "Please either free some disk space on this partition "
138 "and retry or cancel the restore process.")
139 .arg (
"<em>" + DBPath_ +
"</em>",
142 QMessageBox::Retry | QMessageBox::Cancel) == QMessageBox::Cancel)
144 ReportResult (iface,
DumpError { tr (
"Not enough available disk space.") });
149 const auto& newPath = DBPath_ +
".new";
153 if (!QFile::exists (newPath))
156 if (QMessageBox::question (
nullptr,
158 tr (
"%1 already exists. Please either remove the file manually "
159 "and retry or cancel the restore process.")
160 .arg (
"<em>" + newPath +
"</em>"),
161 QMessageBox::Retry | QMessageBox::Cancel) == QMessageBox::Cancel)
163 ReportResult (iface,
DumpError { tr (
"Backup file already exists.") });
168 const auto dumper =
new Dumper { DBPath_, newPath };
170 const auto managed = shared_from_this ();
171 Util::Sequence (
nullptr, dumper->GetFuture ()) >>
175 [iface] (
const Dumper::Error& error)
178 DumpError { tr (
"Unable to restore the database.") +
" " + error.What_ });
180 [iface, newPath, managed] (Dumper::Finished) { managed->HandleDumperFinished (iface, newPath); });
184 void ConsistencyChecker::HandleDumperFinished (QFutureInterface<DumpResult_t> iface,
const QString& to)
186 const auto oldSize = QFileInfo { DBPath_ }.size ();
187 const auto newSize = QFileInfo { to }.size ();
189 const auto& backup = DBPath_ +
".bak";
190 while (!QFile::rename (DBPath_, backup))
191 QMessageBox::critical (
nullptr,
193 tr (
"Unable to backup %1 to %2. Please remove %2 and hit OK.")
197 QFile::rename (to, DBPath_);
199 ReportResult (iface,
DumpFinished { oldSize, newSize });
QFuture< CheckResult_t > StartCheck()
std::variant< Succeeded, Failed > CheckResult_t
static std::shared_ptr< ConsistencyChecker > Create(QString dbPath, QString dialogContext)
std::variant< DumpFinished, DumpError > DumpResult_t
std::variant< Finished, Error > Result_t
FailedImpl(std::shared_ptr< ConsistencyChecker > checker)
QString GenConnectionName(const QString &base)
Generates an unique thread-safe connection name.
auto Visit(const Either< Left, Right > &either, Args &&... args)
SpaceInfo GetSpaceInfo(const QString &path)
Returns the disk space info of the partition containing path.
QString MakePrettySize(qint64 sourcesize)
Makes a formatted size from number.
quint64 Available_
How much space is available to the current user.