ukui-search/libsearch/index/writable-database.cpp

198 lines
5.4 KiB
C++

/*
* Copyright (C) 2022, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*
*/
#include "writable-database.h"
#include <QDir>
#include <QDebug>
#include <memory>
#include "file-utils.h"
#include "index-status-recorder.h"
#include "common.h"
using namespace UkuiSearch;
static QMutex g_basicDatabaseMutex;
static QMutex g_contentDatabaseMutex;
#define DATABASE_TRY(code) try { \
code; \
} \
catch (const Xapian::Error &e)\
{\
qWarning() << "Transaction error," << QString::fromStdString(e.get_description()); \
errorRecord(); \
}
WritableDatabase::WritableDatabase(const DataBaseType &type)
: m_type(type)
{
switch (type) {
case DataBaseType::Basic:
m_path = INDEX_PATH;
m_mutex = &g_basicDatabaseMutex;
break;
case DataBaseType::Content:
m_path = CONTENT_INDEX_PATH;
m_mutex = &g_contentDatabaseMutex;
break;
default:
break;
}
m_mutex->lock();
}
WritableDatabase::~WritableDatabase()
{
if(m_xpDatabase) {
delete m_xpDatabase;
m_xpDatabase = nullptr;
}
m_mutex->unlock();
}
bool WritableDatabase::open()
{
if(m_xpDatabase) {
return true;
}
QDir database(m_path);
if(!database.exists()) {
qDebug() << "Create writable database" << m_path<< database.mkpath(m_path);
}
try {
m_xpDatabase = new Xapian::WritableDatabase(m_path.toStdString(), Xapian::DB_CREATE_OR_OPEN);
} catch(const Xapian::Error &e) {
qWarning() << "Open WritableDatabase fail!" << m_path << QString::fromStdString(e.get_description());
return false;
}
return true;
}
void WritableDatabase::rebuild()
{
if(m_xpDatabase) {
delete m_xpDatabase;
m_xpDatabase = nullptr;
}
QDir database(m_path);
if(database.exists()) {
qDebug() << "Dababase rebuild, remove" << m_path << database.removeRecursively();
} else {
qDebug() << "Dababase rebuild, create" << m_path << database.mkpath(m_path);
}
//更新版本号
switch (m_type) {
case DataBaseType::Basic:
IndexStatusRecorder::getInstance()->setVersion(INDEX_DATABASE_VERSION_KEY, INDEX_DATABASE_VERSION);
break;
case DataBaseType::Content:
IndexStatusRecorder::getInstance()->setVersion(CONTENT_DATABASE_VERSION_KEY, CONTENT_DATABASE_VERSION);
break;
default:
break;
}
}
void WritableDatabase::beginTransation()
{
DATABASE_TRY(m_xpDatabase->begin_transaction();)
}
void WritableDatabase::endTransation()
{
DATABASE_TRY(m_xpDatabase->commit_transaction();)
}
void WritableDatabase::cancelTransation()
{
DATABASE_TRY(m_xpDatabase->cancel_transaction();)
}
void WritableDatabase::commit()
{
DATABASE_TRY(m_xpDatabase->commit();)
}
void WritableDatabase::addDocument(const Document &doc)
{
DATABASE_TRY(m_xpDatabase->replace_document(doc.getUniqueTerm(), doc.getXapianDocument());\
m_xpDatabase->set_metadata(doc.getUniqueTerm(), doc.indexTime());)
}
void WritableDatabase::removeDocument(const QString &path)
{
DATABASE_TRY(m_xpDatabase->delete_document(FileUtils::makeDocUterm(path));)
}
void WritableDatabase::removeDocument(const std::string uniqueTerm)
{
DATABASE_TRY(m_xpDatabase->delete_document(uniqueTerm);
m_xpDatabase->set_metadata(uniqueTerm, "");)
}
void WritableDatabase::removeChildrenDocument(const QString &path)
{
DATABASE_TRY(m_xpDatabase->delete_document("PARENTTERM" + FileUtils::makeDocUterm(path));)
}
void WritableDatabase::setMetaData(const QString &key, const QString &value)
{
DATABASE_TRY(m_xpDatabase->set_metadata(key.toStdString(), value.toStdString());)
}
void WritableDatabase::setMetaData(const std::string &key, const std::string &value)
{
DATABASE_TRY(m_xpDatabase->set_metadata(key, value);)
}
const std::string WritableDatabase::getMetaData(const std::string &key)
{
std::string value;
DATABASE_TRY(value = m_xpDatabase->get_metadata(key);)
return value;
}
QMap<std::string, std::string> WritableDatabase::getIndexTimes()
{
QMap<std::string, std::string> indexTimes;
DATABASE_TRY(
for(Xapian::TermIterator iter = m_xpDatabase->metadata_keys_begin();
iter != m_xpDatabase->metadata_keys_end(); ++iter) {
indexTimes.insert(*iter, m_xpDatabase->get_metadata(*iter));
})
return indexTimes;
}
void WritableDatabase::errorRecord()
{
switch (m_type) {
case DataBaseType::Basic:
IndexStatusRecorder::getInstance()->setStatus(INDEX_DATABASE_STATE_KEY, IndexStatusRecorder::State::Error);
break;
case DataBaseType::Content:
IndexStatusRecorder::getInstance()->setStatus(CONTENT_INDEX_DATABASE_STATE_KEY, IndexStatusRecorder::State::Error);
break;
default:
break;
}
}