Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ void ContentIndexedStrategy::initializeIndexing()

void ContentIndexedStrategy::search(const SearchQuery &query)
{
m_cancelled.store(false);
m_results.clear();

try {
Expand Down Expand Up @@ -256,7 +255,7 @@ void ContentIndexedStrategy::processSearchResults(const Lucene::IndexSearcherPtr
bool enableRetrieval = optAPI.isFullTextRetrievalEnabled();

for (int32_t i = 0; i < docsSize; ++i) {
if (m_cancelled.load()) {
if (m_cancelledRef && m_cancelledRef->load()) {
qInfo() << "Content search cancelled";
break;
}
Expand Down Expand Up @@ -414,7 +413,10 @@ void ContentIndexedStrategy::performContentSearch(const SearchQuery &query)
{
// RAII 守护类:自动管理取消标志的生命周期
// 构造时设置标志,析构时自动清理(即使发生异常)
SearchCancellationGuard guard(&m_cancelled);
// 若 m_cancelledRef 为空(非正常调用链),使用局部 dummy 标志避免空指针解引用
std::atomic<bool> dummyCancelled { false };
std::atomic<bool> *cancelledFlag = m_cancelledRef ? m_cancelledRef : &dummyCancelled;
SearchCancellationGuard guard(cancelledFlag);

try {
// 获取索引目录
Expand Down Expand Up @@ -458,7 +460,7 @@ void ContentIndexedStrategy::performContentSearch(const SearchQuery &query)
Collection<ScoreDocPtr> scoreDocs;
try {
// 创建可取消的收集器
boost::shared_ptr<CancellableCollector> collector = newLucene<CancellableCollector>(&m_cancelled, maxResults);
boost::shared_ptr<CancellableCollector> collector = newLucene<CancellableCollector>(m_cancelledRef, maxResults);

// 执行搜索,使用自定义收集器
qInfo() << "Content search execution start:" << query.keyword();
Expand All @@ -470,7 +472,7 @@ void ContentIndexedStrategy::performContentSearch(const SearchQuery &query)
<< "Total hits:" << collector->getTotalHits()
<< "Collected:" << scoreDocs.size()
<< "Keyword:" << query.keyword()
<< "Cancelled" << m_cancelled.load();
<< "Cancelled" << (m_cancelledRef ? m_cancelledRef->load() : false);
} catch (const SearchCancelledException &e) {
qInfo() << "Content search cancelled during execution";
emit searchFinished(m_results);
Expand Down Expand Up @@ -503,7 +505,8 @@ void ContentIndexedStrategy::performContentSearch(const SearchQuery &query)

void ContentIndexedStrategy::cancel()
{
m_cancelled.store(true);
if (m_cancelledRef)
m_cancelledRef->store(true);
}

DFM_SEARCH_END_NS
14 changes: 8 additions & 6 deletions src/dfm-search/dfm-search-lib/core/genericsearchengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ void GenericSearchEngine::init()
// 连接控制信号(主线程 -> 工作线程)
connect(this, &GenericSearchEngine::requestSearch,
m_worker, &SearchWorker::doSearch);
connect(this, &GenericSearchEngine::requestCancel,
m_worker, &SearchWorker::cancelSearch, Qt::DirectConnection);

// 连接结果信号(工作线程 -> 主线程)
connect(m_worker, &SearchWorker::resultFound,
Expand All @@ -66,6 +64,9 @@ void GenericSearchEngine::init()
// 设置策略工厂
setupStrategyFactory();

// 将引擎级取消标志注入 worker,使策略能即时读取取消状态
m_worker->setEngineCancelledFlag(&m_cancelled);

// 启动工作线程
m_workerThread.start();
}
Expand Down Expand Up @@ -144,11 +145,9 @@ SearchResultExpected GenericSearchEngine::searchSync(const SearchQuery &query)

void GenericSearchEngine::cancel()
{
// 设置取消标志,工作线程通过注入的 flag 即时响应
m_cancelled.store(true);

// 发射信号请求工作线程取消搜索
emit requestCancel();

// 停止批处理定时器
m_batchTimer.stop();

Expand Down Expand Up @@ -218,6 +217,8 @@ void GenericSearchEngine::handleErrorOccurred(const DFMSEARCH::SearchError &erro

SearchResultExpected GenericSearchEngine::doSyncSearch(const SearchQuery &query)
{
// 重置取消标志,避免上次搜索的取消状态残留(与异步 search() 一致)
m_cancelled.store(false);
// 重置同步搜索状态
m_results.clear();
m_lastError = SearchError(SearchErrorCode::Success);
Expand All @@ -244,7 +245,8 @@ SearchResultExpected GenericSearchEngine::doSyncSearch(const SearchQuery &query)

// 检查是否超时
if (!timeoutTimer.isActive()) {
emit requestCancel();
// 超时:设置取消标志通知工作线程停止
m_cancelled.store(true);
return DUnexpected<DFMSEARCH::SearchError> { SearchError(SearchErrorCode::SearchTimeout) };
}

Expand Down
5 changes: 0 additions & 5 deletions src/dfm-search/dfm-search-lib/core/genericsearchengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,6 @@ class GenericSearchEngine : public AbstractSearchEngine
const DFMSEARCH::SearchOptions &options,
DFMSEARCH::SearchType searchType);

/**
* @brief Internal signal to request worker thread to cancel search
*/
void requestCancel();

protected:
/**
* @brief Set up the strategy factory for this search engine
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
#ifndef BASESEARCHSTRATEGY_H
#define BASESEARCHSTRATEGY_H

#include <QObject>

Check warning on line 7 in src/dfm-search/dfm-search-lib/core/searchstrategy/basesearchstrategy.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QObject> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <atomic>

Check warning on line 8 in src/dfm-search/dfm-search-lib/core/searchstrategy/basesearchstrategy.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <atomic> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <dfm-search/searchquery.h>

Check warning on line 9 in src/dfm-search/dfm-search-lib/core/searchstrategy/basesearchstrategy.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <dfm-search/searchquery.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <dfm-search/searchoptions.h>

Check warning on line 10 in src/dfm-search/dfm-search-lib/core/searchstrategy/basesearchstrategy.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <dfm-search/searchoptions.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <dfm-search/searchresult.h>

Check warning on line 11 in src/dfm-search/dfm-search-lib/core/searchstrategy/basesearchstrategy.h

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <dfm-search/searchresult.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <dfm-search/searcherror.h>

DFM_SEARCH_BEGIN_NS
Expand Down Expand Up @@ -53,6 +54,25 @@
*/
virtual void cancel() = 0;

/**
* @brief 注入引擎级取消标志指针(必须注入,否则取消无效)
*
* 策略只读取引擎的 atomic flag:主线程调 GenericSearchEngine::cancel()
* 设 true,工作线程即时响应。flag 必须非空,由 SearchWorker::doSearch
* 创建策略后立即注入。
*
* 注意:不使用 Q_ASSERT,因为它在 Release 构建中会被移除。
* 若传入空指针,保持 m_cancelledRef 为 nullptr 并打印警告。
*/
void setCancelledFlag(std::atomic<bool> *flag)
{
if (!flag) {
qWarning("BaseSearchStrategy::setCancelledFlag: flag is null, cancellation will be ignored");
return;
}
m_cancelledRef = flag;
}

Q_SIGNALS:
/**
* @brief 找到搜索结果信号
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Expand All @@ -72,7 +92,7 @@
protected:
SearchOptions m_options;
SearchResultList m_results;
std::atomic<bool> m_cancelled { false };
std::atomic<bool> *m_cancelledRef { nullptr };
};

DFM_SEARCH_END_NS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ void SearchWorker::doSearch(const SearchQuery &query,
return;
}

// 注入引擎级取消标志,使策略能即时响应取消
if (!m_engineCancelled) {
qWarning("SearchWorker::doSearch: m_engineCancelled is null, aborting search");
emit errorOccurred(SearchError(SearchErrorCode::InternalError));
return;
}
m_strategy->setCancelledFlag(m_engineCancelled);

// 连接信号
connect(m_strategy.get(), &BaseSearchStrategy::resultFound,
this, &SearchWorker::resultFound);
Expand All @@ -55,11 +63,4 @@ void SearchWorker::doSearch(const SearchQuery &query,
m_strategy->search(query);
}

void SearchWorker::cancelSearch()
{
if (m_strategy) {
m_strategy->cancel();
}
}

DFM_SEARCH_END_NS
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@

void setStrategyFactory(std::unique_ptr<SearchStrategyFactory> factory);

void setEngineCancelledFlag(std::atomic<bool> *flag) { m_engineCancelled = flag; }

public Q_SLOTS:

Check warning on line 34 in src/dfm-search/dfm-search-lib/core/searchstrategy/searchworker.h

View workflow job for this annotation

GitHub Actions / cppcheck

There is an unknown macro here somewhere. Configuration is required. If Q_SLOTS is a macro then please configure it.
/**
* @brief 执行搜索操作
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
*/
Expand All @@ -37,11 +39,6 @@
const DFMSEARCH::SearchOptions &options,
DFMSEARCH::SearchType searchType);

/**
* @brief 取消搜索操作
*/
void cancelSearch();

Q_SIGNALS:
/**
* @brief 搜索结果信号
Expand All @@ -61,6 +58,7 @@
private:
std::unique_ptr<SearchStrategyFactory> m_strategyFactory;
std::unique_ptr<BaseSearchStrategy> m_strategy;
std::atomic<bool> *m_engineCancelled { nullptr };
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ void FileNameIndexedStrategy::initializeIndexing()

void FileNameIndexedStrategy::search(const SearchQuery &query)
{
m_cancelled.store(false);
m_results.clear();

if (!QFileInfo::exists(m_indexDir)) {
Expand Down Expand Up @@ -499,7 +498,7 @@ void FileNameIndexedStrategy::executeIndexQuery(const IndexQuery &query, const Q
Collection<ScoreDocPtr> scoreDocs;
try {
// 创建可取消的收集器
boost::shared_ptr<CancellableCollector> collector = newLucene<CancellableCollector>(&m_cancelled, maxResults);
boost::shared_ptr<CancellableCollector> collector = newLucene<CancellableCollector>(m_cancelledRef, maxResults);

// 执行搜索,使用自定义收集器
searcher->search(luceneQuery, collector);
Expand All @@ -523,7 +522,7 @@ void FileNameIndexedStrategy::executeIndexQuery(const IndexQuery &query, const Q

// 实时处理搜索结果
for (int i = 0; i < docsSize; i++) {
if (m_cancelled.load()) {
if (m_cancelledRef && m_cancelledRef->load()) {
qInfo() << "Filename search cancelled";
break;
}
Expand Down Expand Up @@ -827,7 +826,8 @@ BooleanQueryPtr FileNameIndexedStrategy::buildBooleanTermsQuery(const IndexQuery

void FileNameIndexedStrategy::cancel()
{
m_cancelled.store(true);
if (m_cancelledRef)
m_cancelledRef->store(true);
}

DFM_SEARCH_END_NS
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ FileNameRealTimeStrategy::~FileNameRealTimeStrategy() = default;

void FileNameRealTimeStrategy::search(const SearchQuery &query)
{
m_cancelled.store(false);
m_results.clear();

// 从搜索选项获取参数
Expand Down Expand Up @@ -65,7 +64,7 @@ void FileNameRealTimeStrategy::search(const SearchQuery &query)
int count = 0;
QSet<QString> visitedDirs; // 防止符号链接循环

while (!directoryStack.isEmpty() && count < maxResults && !m_cancelled.load()) {
while (!directoryStack.isEmpty() && count < maxResults && !(m_cancelledRef && m_cancelledRef->load())) {
// 取出一个目录进行处理
QString currentDir = directoryStack.pop();

Expand Down Expand Up @@ -102,7 +101,7 @@ void FileNameRealTimeStrategy::search(const SearchQuery &query)

// 处理当前目录中的每个条目
for (const QFileInfo &info : std::as_const(entries)) {
if (m_cancelled.load() || count >= maxResults) {
if ((m_cancelledRef && m_cancelledRef->load()) || count >= maxResults) {
break;
}

Expand Down Expand Up @@ -288,7 +287,8 @@ bool FileNameRealTimeStrategy::matchWildcard(const QString &fileName, const QStr

void FileNameRealTimeStrategy::cancel()
{
m_cancelled.store(true);
if (m_cancelledRef)
m_cancelledRef->store(true);
}

DFM_SEARCH_END_NS
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ void OcrTextIndexedStrategy::initializeIndexing()

void OcrTextIndexedStrategy::search(const SearchQuery &query)
{
m_cancelled.store(false);
m_results.clear();

try {
Expand Down Expand Up @@ -252,7 +251,7 @@ void OcrTextIndexedStrategy::processSearchResults(const Lucene::IndexSearcherPtr
bool enableRetrieval = optAPI.isFullTextRetrievalEnabled();

for (int32_t i = 0; i < docsSize; ++i) {
if (m_cancelled.load()) {
if (m_cancelledRef && m_cancelledRef->load()) {
qInfo() << "OCR text search cancelled";
break;
}
Expand Down Expand Up @@ -413,7 +412,10 @@ void OcrTextIndexedStrategy::processSearchResults(const Lucene::IndexSearcherPtr
void OcrTextIndexedStrategy::performOcrTextSearch(const SearchQuery &query)
{
// RAII guard: automatically manage cancellation flag lifecycle
SearchCancellationGuard guard(&m_cancelled);
// If m_cancelledRef is null (abnormal call chain), use a local dummy to avoid null dereference
std::atomic<bool> dummyCancelled { false };
std::atomic<bool> *cancelledFlag = m_cancelledRef ? m_cancelledRef : &dummyCancelled;
SearchCancellationGuard guard(cancelledFlag);

try {
// Get index directory
Expand Down Expand Up @@ -456,7 +458,7 @@ void OcrTextIndexedStrategy::performOcrTextSearch(const SearchQuery &query)
Collection<ScoreDocPtr> scoreDocs;
try {
// Create cancellable collector
boost::shared_ptr<CancellableCollector> collector = newLucene<CancellableCollector>(&m_cancelled, maxResults);
boost::shared_ptr<CancellableCollector> collector = newLucene<CancellableCollector>(m_cancelledRef, maxResults);

// Execute search with custom collector
qInfo() << "OCR text search execution start:" << query.keyword();
Expand All @@ -468,7 +470,7 @@ void OcrTextIndexedStrategy::performOcrTextSearch(const SearchQuery &query)
<< "Total hits:" << collector->getTotalHits()
<< "Collected:" << scoreDocs.size()
<< "Keyword:" << query.keyword()
<< "Cancelled" << m_cancelled.load();
<< "Cancelled" << (m_cancelledRef ? m_cancelledRef->load() : false);
} catch (const SearchCancelledException &e) {
qInfo() << "OCR text search cancelled during execution";
emit searchFinished(m_results);
Expand Down Expand Up @@ -500,7 +502,8 @@ void OcrTextIndexedStrategy::performOcrTextSearch(const SearchQuery &query)

void OcrTextIndexedStrategy::cancel()
{
m_cancelled.store(true);
if (m_cancelledRef)
m_cancelledRef->store(true);
}

DFM_SEARCH_END_NS
Loading