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 "mtimedb.h"
9#include "enginedebug.h"
10#include "vectorpostingiterator.h"
11#include <algorithm>
12
13using namespace Baloo;
14
15MTimeDB::MTimeDB(MDB_dbi dbi, MDB_txn* txn)
16 : m_txn(txn)
17 , m_dbi(dbi)
18{
19 Q_ASSERT(txn != nullptr);
20 Q_ASSERT(dbi != 0);
21}
22
23MTimeDB::~MTimeDB()
24{
25}
26
27MDB_dbi MTimeDB::create(MDB_txn* txn)
28{
29 MDB_dbi dbi = 0;
30 int rc = mdb_dbi_open(txn, name: "mtimedb", MDB_CREATE | MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_INTEGERDUP, dbi: &dbi);
31 if (rc) {
32 qCWarning(ENGINE) << "MTimeDB::create" << mdb_strerror(err: rc);
33 return 0;
34 }
35
36 return dbi;
37}
38
39MDB_dbi MTimeDB::open(MDB_txn* txn)
40{
41 MDB_dbi dbi = 0;
42 int rc = mdb_dbi_open(txn, name: "mtimedb", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_INTEGERDUP, dbi: &dbi);
43 if (rc) {
44 qCWarning(ENGINE) << "MTimeDB::open" << mdb_strerror(err: rc);
45 return 0;
46 }
47
48 return dbi;
49}
50
51void MTimeDB::put(quint32 mtime, quint64 docId)
52{
53 if (!docId) {
54 qCWarning(ENGINE) << "MTimeDB::put - docId == 0";
55 return;
56 }
57
58 MDB_val key;
59 key.mv_size = sizeof(quint32);
60 key.mv_data = static_cast<void*>(&mtime);
61
62 MDB_val val;
63 val.mv_size = sizeof(quint64);
64 val.mv_data = static_cast<void*>(&docId);
65
66 int rc = mdb_put(txn: m_txn, dbi: m_dbi, key: &key, data: &val, flags: 0);
67 if (rc) {
68 qCWarning(ENGINE) << "MTimeDB::put" << mdb_strerror(err: rc);
69 }
70}
71
72QVector<quint64> MTimeDB::get(quint32 mtime)
73{
74 MDB_val key;
75 key.mv_size = sizeof(quint32);
76 key.mv_data = static_cast<void*>(&mtime);
77
78 QVector<quint64> values;
79
80 MDB_cursor* cursor;
81 mdb_cursor_open(txn: m_txn, dbi: m_dbi, cursor: &cursor);
82
83 MDB_val val{.mv_size: 0, .mv_data: nullptr};
84 int rc = mdb_cursor_get(cursor, key: &key, data: &val, op: MDB_SET);
85 if (rc) {
86 if (rc != MDB_NOTFOUND) {
87 qCWarning(ENGINE) << "MTimeDB::get" << mtime << mdb_strerror(err: rc);
88 }
89 mdb_cursor_close(cursor);
90 return values;
91 }
92
93 values << *static_cast<quint64*>(val.mv_data);
94
95 while (1) {
96 rc = mdb_cursor_get(cursor, key: &key, data: &val, op: MDB_NEXT_DUP);
97 if (rc) {
98 if (rc != MDB_NOTFOUND) {
99 qCWarning(ENGINE) << "MTimeDB::get (loop)" << mtime << mdb_strerror(err: rc);
100 }
101 break;
102 }
103 values << *static_cast<quint64*>(val.mv_data);
104 }
105
106 mdb_cursor_close(cursor);
107 std::sort(first: values.begin(), last: values.end());
108 values.erase(abegin: std::unique(first: values.begin(), last: values.end()), aend: values.end());
109 return values;
110}
111
112void MTimeDB::del(quint32 mtime, quint64 docId)
113{
114 MDB_val key;
115 key.mv_size = sizeof(quint32);
116 key.mv_data = static_cast<void*>(&mtime);
117
118 MDB_val val;
119 val.mv_size = sizeof(quint64);
120 val.mv_data = static_cast<void*>(&docId);
121
122 int rc = mdb_del(txn: m_txn, dbi: m_dbi, key: &key, data: &val);
123 if (rc != 0 && rc != MDB_NOTFOUND) {
124 qCWarning(ENGINE) << "MTimeDB::del" << mtime << docId << mdb_strerror(err: rc);
125 }
126}
127
128//
129// Posting Iterator
130//
131PostingIterator* MTimeDB::iterRange(quint32 beginTime, quint32 endTime)
132{
133 if (endTime < beginTime) {
134 return nullptr;
135 }
136
137 MDB_val key;
138 key.mv_size = sizeof(quint32);
139 key.mv_data = &beginTime;
140
141 MDB_cursor* cursor;
142 mdb_cursor_open(txn: m_txn, dbi: m_dbi, cursor: &cursor);
143
144 MDB_val val{.mv_size: 0, .mv_data: nullptr};
145 int rc = mdb_cursor_get(cursor, key: &key, data: &val, op: MDB_SET_RANGE);
146 if (rc) {
147 if (rc != MDB_NOTFOUND) {
148 qCWarning(ENGINE) << "MTimeDB::iterRange" << beginTime << endTime << mdb_strerror(err: rc);
149 }
150 mdb_cursor_close(cursor);
151 return nullptr;
152 }
153
154 QVector<quint64> results;
155
156 while (1) {
157 quint32 time = *static_cast<quint32*>(key.mv_data);
158 if (time > endTime) {
159 break;
160 }
161 results << *static_cast<quint64*>(val.mv_data);
162
163 rc = mdb_cursor_get(cursor, key: &key, data: &val, op: MDB_NEXT);
164 if (rc) {
165 if (rc != MDB_NOTFOUND) {
166 qCWarning(ENGINE) << "MTimeDB::iterRange (loop)" << beginTime << endTime << mdb_strerror(err: rc);
167 }
168 break;
169 }
170 }
171
172 mdb_cursor_close(cursor);
173
174 if (results.isEmpty()) {
175 return nullptr;
176 }
177 std::sort(first: results.begin(), last: results.end());
178 results.erase(abegin: std::unique(first: results.begin(), last: results.end()), aend: results.end());
179 return new VectorPostingIterator(results);
180}
181
182QMap<quint32, quint64> MTimeDB::toTestMap() const
183{
184 MDB_cursor* cursor;
185 mdb_cursor_open(txn: m_txn, dbi: m_dbi, cursor: &cursor);
186
187 MDB_val key = {.mv_size: 0, .mv_data: nullptr};
188 MDB_val val;
189
190 QMap<quint32, quint64> map;
191 while (1) {
192 int rc = mdb_cursor_get(cursor, key: &key, data: &val, op: MDB_NEXT);
193 if (rc) {
194 qCDebug(ENGINE) << "MTimeDB::toTestMap" << mdb_strerror(err: rc);
195 break;
196 }
197
198 const quint32 time = *(static_cast<quint32*>(key.mv_data));
199 const quint64 id = *(static_cast<quint64*>(val.mv_data));
200 map.insert(key: time, value: id);
201 }
202
203 mdb_cursor_close(cursor);
204 return map;
205}
206

source code of baloo/src/engine/mtimedb.cpp