LeechCraft
0.6.70-18450-gabe19ee3b0
Modular cross-platform feature rich live environment.
Toggle main menu visibility
Loading...
Searching...
No Matches
consistencychecker.cpp
Go to the documentation of this file.
1
/**********************************************************************
2
* LeechCraft - modular cross-platform feature rich internet client.
3
* Copyright (C) 2006-2014 Georg Rudoy
4
*
5
* Distributed under the Boost Software License, Version 1.0.
6
* (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7
**********************************************************************/
8
9
#include "
consistencychecker.h
"
10
#include <memory>
11
#include <QCoreApplication>
12
#include <QFile>
13
#include <QMessageBox>
14
#include <QSqlDatabase>
15
#include <QtConcurrentRun>
16
#include <
util/gui/util.h
>
17
#include <
util/sll/qtutil.h
>
18
#include <
util/sll/visitor.h
>
19
#include <
util/sys/paths.h
>
20
#include <
util/threads/coro.h
>
21
#include <
util/util.h
>
22
#include "
dumper.h
"
23
#include "
util.h
"
24
25
namespace
LC::Util::ConsistencyChecker
26
{
27
namespace
28
{
29
struct
Tr
30
{
31
Q_DECLARE_TR_FUNCTIONS (
LC::Util::ConsistencyChecker
)
32
};
33
34
CheckResult_t
CheckSync (
const
QString& dbPath)
35
{
36
qDebug () <<
"checking"
<< dbPath;
37
const
auto
& connName =
GenConnectionName
(
"ConsistencyChecker_"
+ dbPath);
38
39
auto
db = QSqlDatabase::addDatabase (
"QSQLITE"
_qs, connName);
40
const
auto
remGuard =
MakeScopeGuard
([connName] { QSqlDatabase::removeDatabase (connName); });
41
42
db.setDatabaseName (dbPath);
43
if
(!db.open ())
44
{
45
qWarning () <<
"cannot open the DB, but that's not the kind of errors we're solving."
;
46
return
Succeeded
{};
47
}
48
49
QSqlQuery pragma { db };
50
static
const
auto
checkQuery = qgetenv (
"LC_THOROUGH_SQLITE_CHECK"
) ==
"1"
?
51
"PRAGMA integrity_check;"
_qs :
52
"PRAGMA quick_check;"
_qs;
53
const
auto
isGood = pragma.exec (checkQuery) &&
54
pragma.next () &&
55
pragma.value (0) ==
"ok"
;
56
qDebug () <<
"done checking"
<< dbPath <<
"; db is good?"
<< isGood;
57
if
(isGood)
58
return
Succeeded
{};
59
60
return
Left
{
Failed
{} };
61
}
62
63
Either<RecoverFailed, Void>
CheckRecoverSpace (
const
QString& dbPath)
64
{
65
const
QFileInfo fi { dbPath };
66
const
auto
filesize = fi.size ();
67
68
const
auto
available =
static_cast<
qint64
>
(
GetSpaceInfo
(dbPath).
Available_
);
69
70
qDebug () <<
"db size:"
<< filesize
71
<<
"free space:"
<< available;
72
if
(available >= filesize)
73
return
Void
{};
74
75
return
Left
{
RecoverNoSpace
{ .Available_ = available, .Expected_ = filesize } };
76
}
77
}
78
79
Task<CheckResult_t>
Check
(QString dbPath)
80
{
81
co_return
co_await
QtConcurrent::run (CheckSync, dbPath);
82
}
83
84
Task<RecoverResult_t>
Recover
(QString dbPath)
85
{
86
co_await
CheckRecoverSpace (dbPath);
87
const
auto
& newPath = dbPath +
".new"
;
88
if
(QFile::exists (newPath))
89
co_return
Left
{
RecoverTargetExists
{ newPath } };
90
91
const
auto
dumpProcResult =
co_await
DumpSqlite
(dbPath, newPath);
92
[[maybe_unused]]
const
auto
dumpProcSuccess =
co_await
WithHandler
(dumpProcResult,
93
[] (
const
QString& msg) {
return
RecoverOtherFailure
{ msg }; });
94
95
const
auto
oldSize = QFileInfo { dbPath }.size ();
96
const
auto
newSize = QFileInfo { newPath }.size ();
97
98
const
auto
& backupPath = dbPath +
".bak"
;
99
if
(!QFile::rename (dbPath, backupPath))
100
co_return
Left
{
RecoverTargetExists
{ backupPath } };
101
102
// extremely unlikely if the previous rename succeeded
103
while
(!QFile::rename (newPath, dbPath))
104
{
105
qCritical () <<
"unable to rename"
<< newPath <<
"→"
<< dbPath;
106
const
auto
& msg = Tr::tr (
"Unable to rename %1 to %2. Please check %2 does not exist, and hit OK."
)
107
.arg (newPath, dbPath);
108
QMessageBox::critical (
nullptr
,
"LeechCraft"
_qs, msg);
109
}
110
111
co_return
RecoverFinished
{ .OldFileSize_ = oldSize, .NewFileSize_ = newSize };
112
}
113
114
namespace
115
{
116
QString GetRecoverFailureMessage (
const
RecoverFailed
& failure)
117
{
118
return
Visit
(failure,
119
[&] (RecoverNoSpace space)
120
{
121
return
Tr::tr (
"Not enough space available: "
122
"%1 free while the restored file is expected to be around %2. "
123
"Please either free some disk space on this partition "
124
"and retry or cancel the restore process."
)
125
.arg (
MakePrettySize
(space.Available_),
MakePrettySize
(space.Expected_));
126
},
127
[&] (
const
RecoverTargetExists& exists)
128
{
129
return
Tr::tr (
"Target file %1 already exists, please remove it manually and retry."
)
130
.arg (
FormatName
(exists.Target_));
131
},
132
[&] (
const
RecoverOtherFailure& other)
133
{
134
return
other.Message_;
135
});
136
}
137
}
138
139
Task<RecoverResult_t>
RecoverWithUserInteraction
(QString dbPath, QString diaTitle)
140
{
141
while
(
true
)
142
{
143
const
auto
result =
co_await
Recover
(dbPath);
144
if
(result.IsRight ())
145
co_return
result;
146
147
const
auto
& question = Tr::tr (
"Unable to dump corrupted SQLite database %1."
).arg (
FormatName
(dbPath)) +
148
"<br/><br/>"
_qs +
149
GetRecoverFailureMessage (result.GetLeft ());
150
if
(QMessageBox::question (
nullptr
, diaTitle, question, QMessageBox::Retry | QMessageBox::Cancel) == QMessageBox::Cancel)
151
co_return
result;
152
}
153
}
154
}
LC::Util::Either
Definition
either.h:33
LC::Util::Task
Definition
task.h:155
consistencychecker.h
coro.h
util.h
dumper.h
LC::Util::GenConnectionName
QString GenConnectionName(const QString &base)
Generates an unique thread-safe connection name.
Definition
util.cpp:55
util.h
LC::Util::ConsistencyChecker
Definition
consistencychecker.cpp:26
LC::Util::ConsistencyChecker::Recover
Task< RecoverResult_t > Recover(QString dbPath)
Definition
consistencychecker.cpp:84
LC::Util::ConsistencyChecker::RecoverWithUserInteraction
Task< RecoverResult_t > RecoverWithUserInteraction(QString dbPath, QString diaTitle)
Definition
consistencychecker.cpp:139
LC::Util::ConsistencyChecker::CheckResult_t
Either< Failed, Succeeded > CheckResult_t
Definition
consistencychecker.h:21
LC::Util::ConsistencyChecker::RecoverFailed
std::variant< RecoverNoSpace, RecoverTargetExists, RecoverOtherFailure > RecoverFailed
Definition
consistencychecker.h:38
LC::Util::ConsistencyChecker::Check
Task< CheckResult_t > Check(QString dbPath)
Definition
consistencychecker.cpp:79
LC::Util::MakeScopeGuard
detail::ScopeGuard< F > MakeScopeGuard(const F &f)
Returns an object performing passed function on scope exit.
Definition
util.h:155
LC::Util::DumpSqlite
Task< Either< QString, Void > > DumpSqlite(QString from, QString to)
Definition
dumper.cpp:58
LC::Util::WithHandler
detail::EitherAwaiter< L, R, F > WithHandler(const Either< L, R > &either, F &&errorHandler)
Definition
either.h:82
LC::Util::Visit
auto Visit(const Either< Left, Right > &either, Args &&... args)
Definition
either.h:180
LC::Util::GetSpaceInfo
SpaceInfo GetSpaceInfo(const QString &path)
Returns the disk space info of the partition containing path.
Definition
paths.cpp:155
LC::Util::FormatName
QString FormatName(const QString &name)
HTML-formats the name to let the user know it is not a part of the fixed dialog text.
Definition
util.cpp:114
LC::Util::MakePrettySize
QString MakePrettySize(qint64 sourcesize)
Makes a formatted size from number.
Definition
util.cpp:52
paths.h
qtutil.h
LC::Util::ConsistencyChecker::Failed
Definition
consistencychecker.h:19
LC::Util::ConsistencyChecker::RecoverFinished
Definition
consistencychecker.h:26
LC::Util::ConsistencyChecker::RecoverNoSpace
Definition
consistencychecker.h:32
LC::Util::ConsistencyChecker::RecoverOtherFailure
Definition
consistencychecker.h:37
LC::Util::ConsistencyChecker::RecoverTargetExists
Definition
consistencychecker.h:36
LC::Util::ConsistencyChecker::Succeeded
Definition
consistencychecker.h:20
LC::Util::Left
Definition
either.h:20
LC::Util::SpaceInfo::Available_
quint64 Available_
How much space is available to the current user.
Definition
paths.h:202
LC::Util::Void
A proper void type, akin to unit (or ()) type in functional languages.
Definition
void.h:21
util.h
visitor.h
src
util
db
consistencychecker.cpp
Generated by
1.17.0