12 #include <QSqlDatabase>
13 #include <QMessageBox>
14 #include <QtConcurrentRun>
24 class FailedImpl final :
public ConsistencyChecker::IFailed
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 ());
102 iface.reportStarted ();
104 DumpReinitImpl (iface);
106 return iface.future ();
114 iface.reportFinished (&result);
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); });
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 });