Baloo

documenturldb.cpp
1 /*
2  This file is part of the KDE Baloo project.
3  SPDX-FileCopyrightText: 2015 Vishesh Handa <[email protected]>
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 
14 using namespace Baloo;
15 
16 DocumentUrlDB::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 
23 DocumentUrlDB::~DocumentUrlDB()
24 {
25 }
26 
27 bool 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 
65 bool 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 
78 void 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
92  subDocs = idTreeDb.get(newParentId);
93  sortedIdInsert(subDocs, id);
94  idTreeDb.set(newParentId, subDocs);
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 
105 void 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 
127 void 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
139  sortedIdInsert(subDocs, id);
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 
151 bool 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 
162 QByteArray 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 
197 QVector<quint64> DocumentUrlDB::getChildren(quint64 docId) const
198 {
199  IdTreeDB idTreeDb(m_idTreeDbi, m_txn);
200  return idTreeDb.get(docId);
201 }
202 
203 quint64 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 
223 QMap<quint64, QByteArray> DocumentUrlDB::toTestMap() const
224 {
225  IdTreeDB idTreeDb(m_idTreeDbi, m_txn);
226 
227  QMap<quint64, QVector<quint64>> idTreeMap = idTreeDb.toTestMap();
228  QSet<quint64> allIds;
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 }
bool removeOne(const T &t)
QString & prepend(QChar ch)
QByteArray & prepend(char ch)
QMap::const_iterator cbegin() const const
int lastIndexOf(char ch, int from) const const
QMap::const_iterator cend() const const
Implements storage for docIds without any associated data Instantiated for:
Definition: coding.cpp:11
QByteArray mid(int pos, int len) const const
bool contains(char ch) const const
bool isEmpty() const const
void resize(int size)
KGuiItem add()
QString path(const QString &relativePath)
const char * name(StandardAction id)
bool endsWith(const QByteArray &ba) const const
QSet::iterator insert(const T &value)
void sortedIdInsert(T &vec, const V &id)
Definition: idutils.h:98
virtual bool put(ScriptableExtension *callerPrincipal, quint64 objId, const QString &propName, const QVariant &value)
QFuture< void > map(Sequence &sequence, MapFunctor function)
virtual QVariant get(ScriptableExtension *callerPrincipal, quint64 objId, const QString &propName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Nov 29 2023 03:56:26 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.