Baloo

documenturldb.cpp
1/*
2 This file is part of the KDE Baloo project.
3 SPDX-FileCopyrightText: 2015 Vishesh Handa <vhanda@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.1-or-later
6*/
7
8#include "documenturldb.h"
9#include "postingiterator.h"
10#include "enginedebug.h"
11
12#include <algorithm>
13
14using namespace Baloo;
15
16DocumentUrlDB::DocumentUrlDB(MDB_dbi idTreeDb, MDB_dbi idFilenameDb, MDB_txn* txn)
17 : m_txn(txn)
18 , m_idFilenameDbi(idFilenameDb)
19 , m_idTreeDbi(idTreeDb)
20{
21}
22
23DocumentUrlDB::~DocumentUrlDB()
24{
25}
26
27bool DocumentUrlDB::addPath(const QByteArray& url)
28{
29 Q_ASSERT(!url.isEmpty());
30 Q_ASSERT(!url.endsWith('/'));
31 if (url.isEmpty() || url.endsWith('/')) {
32 return false;
33 }
34
35 IdFilenameDB idFilenameDb(m_idFilenameDbi, m_txn);
36
37 QByteArray arr = url;
38 quint64 id = filePathToId(arr);
39
40 while (id) {
41 if (idFilenameDb.contains(id)) {
42 return true;
43 }
44
45 int pos = arr.lastIndexOf('/');
46 QByteArray name = arr.mid(pos + 1);
47
48 if (pos == 0) {
49 add(id, 0, name);
50 return true;
51 }
52
53 arr.resize(pos);
54 auto parentId = filePathToId(arr);
55 if (!parentId) {
56 return false;
57 }
58 add(id, parentId, name);
59
60 id = parentId;
61 }
62 return false;
63}
64
65bool DocumentUrlDB::put(quint64 docId, quint64 parentId, const QByteArray& filename)
66{
67 Q_ASSERT(docId);
68 Q_ASSERT(!filename.contains('/'));
69 Q_ASSERT(!filename.isEmpty());
70 if (!docId || filename.isEmpty() || filename.contains('/')) {
71 return false;
72 }
73
74 add(docId, parentId, filename);
75 return true;
76}
77
78void DocumentUrlDB::updateUrl(quint64 id, quint64 newParentId, const QByteArray& newName)
79{
80 IdFilenameDB idFilenameDb(m_idFilenameDbi, m_txn);
81 IdTreeDB idTreeDb(m_idTreeDbi, m_txn);
82
83 // Sanity checks
84 auto path = idFilenameDb.get(id);
85 if (path.parentId != newParentId) {
86 // Remove from old parent
87 QVector<quint64> subDocs = idTreeDb.get(path.parentId);
88 if (subDocs.removeOne(id)) {
89 idTreeDb.set(path.parentId, subDocs);
90 }
91 // Add to new parent
95 }
96
97 if ((newName != path.name) || (newParentId != path.parentId)) {
98 qCDebug(ENGINE) << id << "renaming" << path.name << "to" << newName;
99 path.parentId = newParentId;
100 path.name = newName;
101 idFilenameDb.put(id, path);
102 }
103}
104
105void DocumentUrlDB::del(quint64 id)
106{
107 if (!id) {
108 qCWarning(ENGINE) << "del called with invalid docId";
109 return;
110 }
111
112 IdFilenameDB idFilenameDb(m_idFilenameDbi, m_txn);
113 IdTreeDB idTreeDb(m_idTreeDbi, m_txn);
114
115 auto path = idFilenameDb.get(id);
116
117 // Remove from parent
118 QVector<quint64> subDocs = idTreeDb.get(path.parentId);
119 if (subDocs.removeOne(id)) {
120 idTreeDb.set(path.parentId, subDocs);
121 }
122
123 qCDebug(ENGINE) << id << "deleting" << path.name;
124 idFilenameDb.del(id);
125}
126
127void DocumentUrlDB::add(quint64 id, quint64 parentId, const QByteArray& name)
128{
129 if (!id || name.isEmpty()) {
130 return;
131 }
132
133 IdFilenameDB idFilenameDb(m_idFilenameDbi, m_txn);
134 IdTreeDB idTreeDb(m_idTreeDbi, m_txn);
135
136 QVector<quint64> subDocs = idTreeDb.get(parentId);
137
138 // insert if not there
140
141 idTreeDb.set(parentId, subDocs);
142
143 // Update the IdFileName
144 IdFilenameDB::FilePath path;
145 path.parentId = parentId;
146 path.name = name;
147
148 idFilenameDb.put(id, path);
149}
150
151bool DocumentUrlDB::contains(quint64 docId) const
152{
153 if (!docId) {
154 return false;
155 }
156
157 IdFilenameDB idFilenameDb(m_idFilenameDbi, m_txn);
158
159 return idFilenameDb.contains(docId);
160}
161
162QByteArray DocumentUrlDB::get(quint64 docId) const
163{
164 if (!docId) {
165 return QByteArray();
166 }
167
168 IdFilenameDB idFilenameDb(m_idFilenameDbi, m_txn);
169
170 IdFilenameDB::FilePath path;
171 if (!idFilenameDb.get(docId, path)) {
172 return QByteArray();
173 }
174
175 QByteArray ret = '/' + path.name;
176 quint64 id = path.parentId;
177 // arbitrary path depth limit - we have to deal with
178 // possibly corrupted DBs out in the wild
179 int depth_limit = 512;
180
181 while (id) {
182 if (!idFilenameDb.get(id, path)) {
183 return QByteArray();
184 }
185 if (!depth_limit--) {
186 return QByteArray();
187 }
188 path.name.prepend('/');
189
190 ret.prepend(path.name);
191 id = path.parentId;
192 }
193
194 return ret;
195}
196
197QVector<quint64> DocumentUrlDB::getChildren(quint64 docId) const
198{
199 IdTreeDB idTreeDb(m_idTreeDbi, m_txn);
200 return idTreeDb.get(docId);
201}
202
203quint64 DocumentUrlDB::getId(quint64 docId, const QByteArray& fileName) const
204{
205 if (fileName.isEmpty()) {
206 return 0;
207 }
208
209 IdFilenameDB idFilenameDb(m_idFilenameDbi, m_txn);
210 IdTreeDB idTreeDb(m_idTreeDbi, m_txn);
211
212 const QVector<quint64> subFiles = idTreeDb.get(docId);
213 IdFilenameDB::FilePath path;
214 for (quint64 id : subFiles) {
215 if (idFilenameDb.get(id, path) && (path.name == fileName)) {
216 return id;
217 }
218 }
219
220 return 0;
221}
222
223QMap<quint64, QByteArray> DocumentUrlDB::toTestMap() const
224{
225 IdTreeDB idTreeDb(m_idTreeDbi, m_txn);
226
229
230 for (auto it = idTreeMap.cbegin(); it != idTreeMap.cend(); it++) {
231 allIds.insert(it.key());
232 for (quint64 id : it.value()) {
233 allIds.insert(id);
234 }
235 }
236
238 for (quint64 id : allIds) {
239 if (id) {
240 QByteArray path = get(id);
241 // FIXME: this prevents sanitizing
242 // reactivate Q_ASSERT(!path.isEmpty());
243 map.insert(id, path);
244 }
245 }
246
247 return map;
248}
Implements storage for docIds without any associated data Instantiated for:
Definition coding.cpp:11
void sortedIdInsert(T &vec, const V &id)
Definition idutils.h:98
QString path(const QString &relativePath)
QString name(StandardShortcut id)
bool contains(QByteArrayView bv) const const
bool endsWith(QByteArrayView bv) const const
bool isEmpty() const const
const_iterator cbegin() const const
const_iterator cend() const const
bool contains(const AT &value) const const
iterator insert(const_iterator before, parameter_type value)
qsizetype lastIndexOf(const AT &value, qsizetype from) const const
QList< T > mid(qsizetype pos, qsizetype length) const const
void prepend(parameter_type value)
bool removeOne(const AT &t)
void resize(qsizetype size)
bool isEmpty() const const
QString & prepend(QChar ch)
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:16 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.