File indexing completed on 2024-04-21 03:51:40
0001 /* 0002 This file is part of the KDE Baloo project. 0003 SPDX-FileCopyrightText: 2015 Vishesh Handa <vhanda@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-or-later 0006 */ 0007 0008 #include "idtreedb.h" 0009 #include "enginedebug.h" 0010 #include "postingiterator.h" 0011 0012 #include <algorithm> 0013 0014 using namespace Baloo; 0015 0016 IdTreeDB::IdTreeDB(MDB_dbi dbi, MDB_txn* txn) 0017 : m_txn(txn) 0018 , m_dbi(dbi) 0019 { 0020 Q_ASSERT(txn != nullptr); 0021 Q_ASSERT(dbi != 0); 0022 } 0023 0024 MDB_dbi IdTreeDB::create(MDB_txn* txn) 0025 { 0026 MDB_dbi dbi = 0; 0027 int rc = mdb_dbi_open(txn, "idtree", MDB_CREATE | MDB_INTEGERKEY, &dbi); 0028 if (rc) { 0029 qCWarning(ENGINE) << "IdTreeDB::create" << mdb_strerror(rc); 0030 return 0; 0031 } 0032 0033 return dbi; 0034 } 0035 0036 MDB_dbi IdTreeDB::open(MDB_txn* txn) 0037 { 0038 MDB_dbi dbi = 0; 0039 int rc = mdb_dbi_open(txn, "idtree", MDB_INTEGERKEY, &dbi); 0040 if (rc) { 0041 qCWarning(ENGINE) << "IdTreeDB::open" << mdb_strerror(rc); 0042 return 0; 0043 } 0044 0045 return dbi; 0046 } 0047 0048 void IdTreeDB::set(quint64 docId, const QVector<quint64> &subDocIds) 0049 { 0050 Q_ASSERT(!subDocIds.contains(0)); 0051 0052 MDB_val key; 0053 key.mv_size = sizeof(quint64); 0054 key.mv_data = static_cast<void*>(&docId); 0055 0056 int rc; 0057 if (subDocIds.empty()) { 0058 rc = mdb_del(m_txn, m_dbi, &key, nullptr); 0059 if (rc == MDB_NOTFOUND) { 0060 rc = 0; 0061 } 0062 } else { 0063 MDB_val val; 0064 val.mv_size = subDocIds.size() * sizeof(quint64); 0065 val.mv_data = static_cast<void*>(const_cast<quint64*>(subDocIds.constData())); 0066 0067 rc = mdb_put(m_txn, m_dbi, &key, &val, 0); 0068 } 0069 if (rc) { 0070 qCWarning(ENGINE) << "IdTreeDB::set" << mdb_strerror(rc); 0071 } 0072 } 0073 0074 QVector<quint64> IdTreeDB::get(quint64 docId) 0075 { 0076 MDB_val key; 0077 key.mv_size = sizeof(quint64); 0078 key.mv_data = static_cast<void*>(&docId); 0079 0080 MDB_val val{0, nullptr}; 0081 int rc = mdb_get(m_txn, m_dbi, &key, &val); 0082 if (rc) { 0083 if (rc != MDB_NOTFOUND) { 0084 qCDebug(ENGINE) << "IdTreeDB::get" << docId << mdb_strerror(rc); 0085 } 0086 return QVector<quint64>(); 0087 } 0088 0089 // FIXME: This still makes a copy of the data. Perhaps we can avoid that? 0090 QVector<quint64> list(val.mv_size / sizeof(quint64)); 0091 memcpy(list.data(), val.mv_data, val.mv_size); 0092 0093 return list; 0094 } 0095 0096 // 0097 // Iter 0098 // 0099 class IdTreePostingIterator : public PostingIterator { 0100 public: 0101 IdTreePostingIterator(const IdTreeDB& db, const QVector<quint64> &list) 0102 : m_db(db), m_pos(-1), m_idList(list) {} 0103 0104 quint64 docId() const override { 0105 if (m_pos >= 0 && m_pos < m_resultList.size()) { 0106 return m_resultList[m_pos]; 0107 } 0108 return 0; 0109 } 0110 0111 quint64 next() override { 0112 if (m_resultList.isEmpty() && m_idList.isEmpty()) { 0113 return 0; 0114 } 0115 0116 if (m_resultList.isEmpty()) { 0117 while (!m_idList.isEmpty()) { 0118 quint64 id = m_idList.takeLast(); 0119 m_idList << m_db.get(id); 0120 m_resultList << id; 0121 } 0122 std::sort(m_resultList.begin(), m_resultList.end()); 0123 m_pos = 0; 0124 } 0125 else { 0126 if (m_pos < m_resultList.size()) { 0127 m_pos++; 0128 } else { 0129 m_resultList.clear(); 0130 } 0131 } 0132 0133 if (m_pos < m_resultList.size()) { 0134 return m_resultList[m_pos]; 0135 } else { 0136 return 0; 0137 } 0138 } 0139 0140 private: 0141 IdTreeDB m_db; 0142 int m_pos; 0143 QVector<quint64> m_idList; 0144 QVector<quint64> m_resultList; 0145 }; 0146 0147 PostingIterator* IdTreeDB::iter(quint64 docId) 0148 { 0149 Q_ASSERT(docId > 0); 0150 0151 QVector<quint64> list = {docId}; 0152 return new IdTreePostingIterator(*this, list); 0153 } 0154 0155 QMap<quint64, QVector<quint64>> IdTreeDB::toTestMap() const 0156 { 0157 MDB_cursor* cursor; 0158 mdb_cursor_open(m_txn, m_dbi, &cursor); 0159 0160 MDB_val key = {0, nullptr}; 0161 MDB_val val; 0162 0163 QMap<quint64, QVector<quint64>> map; 0164 while (1) { 0165 int rc = mdb_cursor_get(cursor, &key, &val, MDB_NEXT); 0166 if (rc == MDB_NOTFOUND) { 0167 break; 0168 } 0169 if (rc) { 0170 qCDebug(ENGINE) << "IdTreeDB::toTestMap" << mdb_strerror(rc); 0171 break; 0172 } 0173 0174 const quint64 id = *(static_cast<quint64*>(key.mv_data)); 0175 0176 QVector<quint64> list(val.mv_size / sizeof(quint64)); 0177 memcpy(list.data(), val.mv_data, val.mv_size); 0178 0179 map.insert(id, list); 0180 } 0181 0182 mdb_cursor_close(cursor); 0183 return map; 0184 }