diff options
author | Yury Melnichek <melnichek@gmail.com> | 2011-06-05 20:52:42 +0400 |
---|---|---|
committer | Alex Zolotarev <alex@maps.me> | 2015-09-23 01:19:10 +0300 |
commit | 21c7b3035bc13af9a8e26d47136ee53b84b092fb (patch) | |
tree | d957399137f95eed04fe7c3de42b1c38284cfb44 /search | |
parent | 46c2f39910649982f00ace94cc32a3c28cd3ae2b (diff) |
[search] Implement query termination. Make search slow to test it :)
Diffstat (limited to 'search')
-rw-r--r-- | search/engine.cpp | 54 | ||||
-rw-r--r-- | search/engine.hpp | 6 | ||||
-rw-r--r-- | search/query.cpp | 55 | ||||
-rw-r--r-- | search/query.hpp | 7 | ||||
-rw-r--r-- | search/search_tests/query_test.cpp | 16 |
5 files changed, 116 insertions, 22 deletions
diff --git a/search/engine.cpp b/search/engine.cpp index a6a7c9209f..92f745a865 100644 --- a/search/engine.cpp +++ b/search/engine.cpp @@ -11,30 +11,76 @@ namespace search { Engine::Engine(IndexType const * pIndex) - : m_pIndex(pIndex), m_pRunner(new threads::ConcurrentRunner) + : m_pIndex(pIndex), m_pRunner(new threads::ConcurrentRunner), m_pLastQuery(NULL), + m_queriesActive(0) { } +Engine::~Engine() +{ + LOG(LDEBUG, (m_queriesActive)); + ASSERT_EQUAL(m_queriesActive, 0, ()); +} + void Engine::Search(string const & queryText, m2::RectD const & rect, function<void (Result const &)> const & f) { + LOG(LDEBUG, (queryText, rect)); + + impl::Query * pQuery = new impl::Query(queryText, rect, m_pIndex, this); + { threads::MutexGuard mutexGuard(m_mutex); UNUSED_VALUE(mutexGuard); + + ASSERT_GREATER_OR_EQUAL(m_queriesActive, 0, ()); + if (m_pLastQuery) + { + LOG(LDEBUG, ("Stopping previous", m_pLastQuery->GetQueryText(), m_pLastQuery->GetViewport())); m_pLastQuery->SetTerminateFlag(); + } + + m_pLastQuery = pQuery; + ++m_queriesActive; + LOG(LDEBUG, ("Queries active", m_queriesActive)); } - impl::Query * pQuery = new impl::Query(queryText, rect, m_pIndex); m_pRunner->Run(bind(&impl::Query::SearchAndDestroy, pQuery, f)); } -void Engine::OnQueryDelete() +void Engine::OnQueryDelete(impl::Query * pQuery) +{ + threads::MutexGuard mutexGuard(m_mutex); + UNUSED_VALUE(mutexGuard); + + ASSERT_GREATER_OR_EQUAL(m_queriesActive, 1, ()); + + --m_queriesActive; + LOG(LDEBUG, ("Queries active", m_queriesActive)); + LOG(LDEBUG, ("Query destroyed", pQuery->GetQueryText(), pQuery->GetViewport())); + + if (m_pLastQuery == pQuery) + { + LOG(LDEBUG, ("Last query destroyed")); + m_pLastQuery = NULL; + } +} + +void Engine::StopEverything() { threads::MutexGuard mutexGuard(m_mutex); UNUSED_VALUE(mutexGuard); - m_pLastQuery = NULL; + + ASSERT_GREATER_OR_EQUAL(m_queriesActive, 0, ()); + LOG(LINFO, (m_queriesActive, m_pLastQuery)); + + if (m_pLastQuery) + { + LOG(LDEBUG, ("Stopping previous", m_pLastQuery->GetQueryText(), m_pLastQuery->GetViewport())); + m_pLastQuery->SetTerminateFlag(); + } } } // namespace search diff --git a/search/engine.hpp b/search/engine.hpp index bd3983b951..ce983fb3b2 100644 --- a/search/engine.hpp +++ b/search/engine.hpp @@ -23,18 +23,22 @@ public: typedef Index<FileReader>::Type IndexType; explicit Engine(IndexType const * pIndex); + ~Engine(); void Search(string const & query, m2::RectD const & rect, function<void (Result const &)> const & f); - void OnQueryDelete(); + void StopEverything(); + + void OnQueryDelete(impl::Query *); private: IndexType const * m_pIndex; scoped_ptr<threads::IRunner> m_pRunner; threads::Mutex m_mutex; impl::Query * volatile m_pLastQuery; + int volatile m_queriesActive; }; } // namespace search diff --git a/search/query.cpp b/search/query.cpp index fb84f82a8b..90e7d38602 100644 --- a/search/query.cpp +++ b/search/query.cpp @@ -4,7 +4,9 @@ #include "string_match.hpp" #include "../indexer/feature_visibility.hpp" #include "../indexer/mercator.hpp" +#include "../base/exception.hpp" #include "../base/stl_add.hpp" +#include "../std/scoped_ptr.hpp" namespace search { @@ -60,12 +62,20 @@ inline KeywordMatcher MakeMatcher(vector<strings::UniString> const & tokens, struct FeatureProcessor { + DECLARE_EXCEPTION(StopException, RootException); + Query & m_query; explicit FeatureProcessor(Query & query) : m_query(query) {} void operator () (FeatureType const & feature) const { + if (m_query.GetTerminateFlag()) + { + LOG(LDEBUG, ("Found terminate search flag", m_query.GetQueryText(), m_query.GetViewport())); + MYTHROW(StopException, ()); + } + KeywordMatcher matcher(MakeMatcher(m_query.GetKeywords(), m_query.GetPrefix())); feature.ForEachNameRef(matcher); if (matcher.GetPrefixMatchScore() <= GetMaxPrefixMatchScore(m_query.GetPrefix().size())) @@ -89,9 +99,10 @@ struct FeatureProcessor } // unnamed namespace -Query::Query(string const & query, m2::RectD const & viewport, IndexType const * pIndex) +Query::Query(string const & query, m2::RectD const & viewport, IndexType const * pIndex, + Engine * pEngine) : m_queryText(query), m_viewport(viewport), m_pIndex(pIndex ? new IndexType(*pIndex) : NULL), - m_bTerminate(false) + m_pEngine(pEngine), m_bTerminate(false) { search::Delimiters delims; SplitAndNormalizeAndSimplifyString(query, MakeBackInsertFunctor(m_keywords), delims); @@ -102,6 +113,12 @@ Query::Query(string const & query, m2::RectD const & viewport, IndexType const * } } +Query::~Query() +{ + if (m_pEngine) + m_pEngine->OnQueryDelete(this); +} + void Query::Search(function<void (Result const &)> const & f) { // Lat lon matching. @@ -128,7 +145,7 @@ void Query::Search(function<void (Result const &)> const & f) if (!m_prefix.empty()) { KeywordMatcher matcher = MakeMatcher(vector<strings::UniString>(), m_prefix); - LOG(LINFO, (m_prefix)); + // LOG(LINFO, (m_prefix)); matcher.ProcessNameToken("", strings::MakeUniString("restaurant")); uint32_t const matchScore = matcher.GetMatchScore(); if (matcher.GetPrefixMatchScore() <= GetMaxPrefixMatchScore(m_prefix.size()) && @@ -144,13 +161,33 @@ void Query::Search(function<void (Result const &)> const & f) // Feature matching. FeatureProcessor featureProcessor(*this); int const scale = scales::GetScaleLevel(m_viewport) + 1; + + try + { + m_pIndex->ForEachInRect(featureProcessor, + m2::RectD(MercatorBounds::minX, MercatorBounds::minY, + MercatorBounds::maxX, MercatorBounds::maxY), + // m_viewport, + scales::GetUpperWorldScale()); + } + catch (FeatureProcessor::StopException &) + { + LOG(LDEBUG, ("FeatureProcessor::StopException")); + } + if (m_bTerminate) + return; + if (scale > scales::GetUpperWorldScale()) { - m_pIndex->ForEachInRect(featureProcessor, m_viewport, scales::GetUpperWorldScale()); - if (m_bTerminate) - return; + try + { + m_pIndex->ForEachInRect(featureProcessor, m_viewport, min(scales::GetUpperScale(), scale)); + } + catch (FeatureProcessor::StopException &) + { + LOG(LDEBUG, ("FeatureProcessor::StopException")); + } } - m_pIndex->ForEachInRect(featureProcessor, m_viewport, min(scales::GetUpperScale(), scale)); if (m_bTerminate) return; @@ -163,12 +200,14 @@ void Query::Search(function<void (Result const &)> const & f) } for (vector<Result>::const_reverse_iterator it = results.rbegin(); it != results.rend(); ++it) f(*it); + f(Result(string(), string())); // Send last search result marker. } void Query::SearchAndDestroy(function<void (const Result &)> const & f) { + scoped_ptr<Query> scopedThis(this); + UNUSED_VALUE(scopedThis); Search(f); - delete this; } void Query::AddResult(IntermediateResult const & result) diff --git a/search/query.hpp b/search/query.hpp index cb77e98d8c..f960fecbb4 100644 --- a/search/query.hpp +++ b/search/query.hpp @@ -22,7 +22,9 @@ class Query public: typedef Engine::IndexType IndexType; - Query(string const & query, m2::RectD const & viewport, IndexType const * pIndex); + Query(string const & query, m2::RectD const & viewport, IndexType const * pIndex, + Engine * pEngine); + ~Query(); // Search with parameters, passed in constructor. void Search(function<void (Result const &)> const & f); @@ -35,7 +37,9 @@ public: // Set a flag that query is not active any more and should terminate. void SetTerminateFlag() volatile { m_bTerminate = true; } + bool GetTerminateFlag() const { return m_bTerminate; } + string const & GetQueryText() const { return m_queryText; } m2::RectD const & GetViewport() const { return m_viewport; } vector<strings::UniString> const & GetKeywords() const { return m_keywords; } strings::UniString const & GetPrefix() const { return m_prefix; } @@ -52,6 +56,7 @@ private: priority_queue<IntermediateResult> m_results; + Engine * m_pEngine; bool volatile m_bTerminate; }; diff --git a/search/search_tests/query_test.cpp b/search/search_tests/query_test.cpp index 2857ae9853..1451445013 100644 --- a/search/search_tests/query_test.cpp +++ b/search/search_tests/query_test.cpp @@ -13,16 +13,16 @@ UNIT_TEST(QueryParseKeywords_Smoke) vector<UniString> expected; expected.push_back(MakeUniString("minsk")); expected.push_back(MakeUniString("belarus")); - TEST_EQUAL(expected, Query("minsk belarus ", m2::RectD(), NULL).GetKeywords(), ()); - TEST_EQUAL(MakeUniString(""), Query("minsk belarus ", m2::RectD(), NULL).GetPrefix(), ()); - TEST_EQUAL(expected, Query("minsk belarus ma", m2::RectD(), NULL).GetKeywords(), ()); - TEST_EQUAL(MakeUniString("ma"), Query("minsk belarus ma", m2::RectD(), NULL).GetPrefix(), ()); + TEST_EQUAL(expected, Query("minsk belarus ", m2::RectD(), 0, 0).GetKeywords(), ()); + TEST_EQUAL(MakeUniString(""), Query("minsk belarus ", m2::RectD(), 0, 0).GetPrefix(), ()); + TEST_EQUAL(expected, Query("minsk belarus ma", m2::RectD(), 0, 0).GetKeywords(), ()); + TEST_EQUAL(MakeUniString("ma"), Query("minsk belarus ma", m2::RectD(), 0, 0).GetPrefix(), ()); } UNIT_TEST(QueryParseKeywords_Empty) { - TEST_EQUAL(vector<UniString>(), Query("", m2::RectD(), NULL).GetKeywords(), ()); - TEST_EQUAL(MakeUniString(""), Query("", m2::RectD(), NULL).GetPrefix(), ()); - TEST_EQUAL(vector<UniString>(), Query("Z", m2::RectD(), NULL).GetKeywords(), ()); - TEST_EQUAL(MakeUniString("z"), Query("Z", m2::RectD(), NULL).GetPrefix(), ()); + TEST_EQUAL(vector<UniString>(), Query("", m2::RectD(), 0, 0).GetKeywords(), ()); + TEST_EQUAL(MakeUniString(""), Query("", m2::RectD(), 0, 0).GetPrefix(), ()); + TEST_EQUAL(vector<UniString>(), Query("Z", m2::RectD(), 0, 0).GetKeywords(), ()); + TEST_EQUAL(MakeUniString("z"), Query("Z", m2::RectD(), 0, 0).GetPrefix(), ()); } |