Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/search
diff options
context:
space:
mode:
authorYury Melnichek <melnichek@gmail.com>2011-06-05 20:52:42 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:19:10 +0300
commit21c7b3035bc13af9a8e26d47136ee53b84b092fb (patch)
treed957399137f95eed04fe7c3de42b1c38284cfb44 /search
parent46c2f39910649982f00ace94cc32a3c28cd3ae2b (diff)
[search] Implement query termination. Make search slow to test it :)
Diffstat (limited to 'search')
-rw-r--r--search/engine.cpp54
-rw-r--r--search/engine.hpp6
-rw-r--r--search/query.cpp55
-rw-r--r--search/query.hpp7
-rw-r--r--search/search_tests/query_test.cpp16
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(), ());
}