2022-10-26 18:01:40 +08:00
|
|
|
/*
|
|
|
|
* 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"
|
2022-12-02 13:48:59 +08:00
|
|
|
#include "common.h"
|
|
|
|
|
2022-10-26 18:01:40 +08:00
|
|
|
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()) {
|
2022-12-05 15:58:33 +08:00
|
|
|
qDebug() << "Create writable database" << m_path<< database.mkpath(m_path);
|
2022-10-26 18:01:40 +08:00
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
2022-12-02 13:48:59 +08:00
|
|
|
|
|
|
|
//更新版本号
|
|
|
|
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;
|
|
|
|
}
|
2022-10-26 18:01:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2022-12-05 15:58:33 +08:00
|
|
|
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));)
|
2022-10-26 18:01:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2022-12-02 13:48:59 +08:00
|
|
|
IndexStatusRecorder::getInstance()->setStatus(INDEX_DATABASE_STATE_KEY, IndexStatusRecorder::State::Error);
|
2022-10-26 18:01:40 +08:00
|
|
|
break;
|
|
|
|
case DataBaseType::Content:
|
2022-12-02 13:48:59 +08:00
|
|
|
IndexStatusRecorder::getInstance()->setStatus(CONTENT_INDEX_DATABASE_STATE_KEY, IndexStatusRecorder::State::Error);
|
2022-10-26 18:01:40 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|